/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.internal.provisional.action.ICoolBarManager2; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.IMemento; import org.eclipse.ui.INavigationHistory; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveRegistry; import org.eclipse.ui.IReusableEditor; import org.eclipse.ui.ISaveablePart; import org.eclipse.ui.ISaveablesLifecycleListener; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IShowEditorInput; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.MultiPartInitException; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.SubActionBars; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.internal.StartupThreading.StartupRunnable; import org.eclipse.ui.internal.dialogs.CustomizePerspectiveDialog; import org.eclipse.ui.internal.dnd.SwtUtil; import org.eclipse.ui.internal.intro.IIntroConstants; import org.eclipse.ui.internal.misc.UIListenerLogging; import org.eclipse.ui.internal.misc.UIStats; import org.eclipse.ui.internal.registry.ActionSetRegistry; import org.eclipse.ui.internal.registry.EditorDescriptor; import org.eclipse.ui.internal.registry.EditorRegistry; import org.eclipse.ui.internal.registry.IActionSetDescriptor; import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; import org.eclipse.ui.internal.registry.PerspectiveDescriptor; import org.eclipse.ui.internal.registry.UIExtensionTracker; import org.eclipse.ui.internal.tweaklets.GrabFocus; import org.eclipse.ui.internal.tweaklets.TabBehaviour; import org.eclipse.ui.internal.tweaklets.Tweaklets; import org.eclipse.ui.internal.tweaklets.WorkbenchImplementation; import org.eclipse.ui.internal.util.PrefUtil; import org.eclipse.ui.internal.util.Util; import org.eclipse.ui.intro.IIntroManager; import org.eclipse.ui.intro.IIntroPart; import org.eclipse.ui.model.IWorkbenchAdapter; import org.eclipse.ui.part.AbstractMultiEditor; import org.eclipse.ui.presentations.IStackPresentationSite; /** * A collection of views and editors in a workbench. */ public class WorkbenchPage extends CompatibleWorkbenchPage implements IWorkbenchPage { private static final String ATT_AGGREGATE_WORKING_SET_ID = "aggregateWorkingSetId"; //$NON-NLS-1$ protected WorkbenchWindow window; private IAdaptable input; private IWorkingSet workingSet; private AggregateWorkingSet aggregateWorkingSet; private Composite composite; //Could be delete. This information is in the active part list; private ActivationList activationList = new ActivationList(); private EditorManager editorMgr; private EditorAreaHelper editorPresentation; private ArrayList removedEditors = new ArrayList(); private ListenerList propertyChangeListeners = new ListenerList(); private PageSelectionService selectionService = new PageSelectionService( this); private WorkbenchPagePartList partList = new WorkbenchPagePartList(selectionService); private IActionBars actionBars; private ActionSetManager actionSets; private ViewFactory viewFactory; private PerspectiveList perspList = new PerspectiveList(); private PerspectiveDescriptor deferredActivePersp; private NavigationHistory navigationHistory = new NavigationHistory(this); private IStickyViewManager stickyViewMan = StickyViewManager.getInstance(this); /** * If we're in the process of activating a part, this points to the new part. * Otherwise, this is null. */ private IWorkbenchPartReference partBeingActivated = null; /** * If a part is being opened, don't allow a forceFocus() to request * its activation as well. * @since 3.4 */ private boolean partBeingOpened = false; /** * Contains a list of perspectives that may be dirty due to plugin * installation and removal. */ private Set dirtyPerspectives = new HashSet(); private IPropertyChangeListener workingSetPropertyChangeListener = new IPropertyChangeListener() { /* * Remove the working set from the page if the working set is deleted. */ public void propertyChange(PropertyChangeEvent event) { String property = event.getProperty(); if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) { if(event.getOldValue().equals(workingSet)) { setWorkingSet(null); } // room for optimization here List newList = new ArrayList(Arrays.asList(workingSets)); if (newList.remove(event.getOldValue())) { setWorkingSets((IWorkingSet []) newList .toArray(new IWorkingSet [newList.size()])); } } } }; private ActionSwitcher actionSwitcher = new ActionSwitcher(); private IExtensionTracker tracker; // Deferral count... delays disposing parts and sending certain events if nonzero private int deferCount = 0; // Parts waiting to be disposed private List pendingDisposals = new ArrayList(); private IExtensionChangeHandler perspectiveChangeHandler = new IExtensionChangeHandler() { /* (non-Javadoc) * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[]) */ public void removeExtension(IExtension extension, Object[] objects) { boolean suggestReset = false; for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof DirtyPerspectiveMarker) { String id = ((DirtyPerspectiveMarker)objects[i]).perspectiveId; if (!dirtyPerspectives.remove(id)) { dirtyPerspectives.add(id); // otherwise we will be dirty } PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective(); if (persp == null || persp.hasCustomDefinition()) { continue; } if (persp.getId().equals(id)) { suggestReset = true; } } } if (suggestReset) { suggestReset(); } } /* (non-Javadoc) * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension) */ public void addExtension(IExtensionTracker tracker, IExtension extension) { if (WorkbenchPage.this != getWorkbenchWindow().getActivePage()) { return; } // Get the current perspective. PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective(); if (persp == null) { return; } String currentId = persp.getId(); IConfigurationElement[] elements = extension.getConfigurationElements(); boolean suggestReset = false; for (int i = 0; i < elements.length; i++) { // If any of these refer to the current perspective, output // a message saying this perspective will need to be reset // in order to see the changes. For any other case, the // perspective extension registry will be rebuilt anyway so // just ignore it. String id = elements[i].getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID); if (id == null) { continue; } if (id.equals(currentId) && !persp.hasCustomDefinition()) { suggestReset = true; } else { dirtyPerspectives.add(id); } DirtyPerspectiveMarker marker = new DirtyPerspectiveMarker(id); tracker.registerObject(extension, marker, IExtensionTracker.REF_STRONG); } if (suggestReset) { suggestReset(); } } }; private IWorkingSet[] workingSets = new IWorkingSet[0]; private String aggregateWorkingSetId; private IExtensionPoint getPerspectiveExtensionPoint() { // RAP [bm]: // return Platform.getExtensionRegistry().getExtensionPoint(PlatformUI.PLUGIN_ID, IWorkbenchRegistryConstants.PL_PERSPECTIVE_EXTENSIONS); return Platform.getExtensionRegistry().getExtensionPoint(PlatformUI.PLUGIN_EXTENSION_NAME_SPACE, IWorkbenchRegistryConstants.PL_PERSPECTIVE_EXTENSIONS); // RAPEND: [bm] } /** * Manages editor contributions and action set part associations. */ private class ActionSwitcher { private IWorkbenchPart activePart; private IEditorPart topEditor; private ArrayList oldActionSets = new ArrayList(); /** * Updates the contributions given the new part as the active part. * * @param newPart * the new active part, may be <code>null</code> */ public void updateActivePart(IWorkbenchPart newPart) { if (activePart == newPart) { return; } boolean isNewPartAnEditor = newPart instanceof IEditorPart; if (isNewPartAnEditor) { String oldId = null; if (topEditor != null) { oldId = topEditor.getSite().getId(); } String newId = newPart.getSite().getId(); // if the active part is an editor and the new editor // is the same kind of editor, then we don't have to do // anything if (activePart == topEditor && newId.equals(oldId)) { activePart = newPart; topEditor = (IEditorPart) newPart; return; } // remove the contributions of the old editor // if it is a different kind of editor if (oldId != null && !oldId.equals(newId)) { deactivateContributions(topEditor, true); } // if a view was the active part, disable its contributions if (activePart != null && activePart != topEditor) { deactivateContributions(activePart, true); } // show (and enable) the contributions of the new editor // if it is a different kind of editor or if the // old active part was a view if (!newId.equals(oldId) || activePart != topEditor) { activateContributions(newPart, true); } } else if (newPart == null) { if (activePart != null) { // remove all contributions deactivateContributions(activePart, true); } } else { // new part is a view // if old active part is a view, remove all contributions, // but if old part is an editor only disable if (activePart != null) { deactivateContributions(activePart, activePart instanceof IViewPart); } activateContributions(newPart, true); } ArrayList newActionSets = null; if (isNewPartAnEditor || (activePart == topEditor && newPart == null)) { newActionSets = calculateActionSets(newPart, null); } else { newActionSets = calculateActionSets(newPart, topEditor); } if (!updateActionSets(newActionSets)) { updateActionBars(); } if (isNewPartAnEditor) { topEditor = (IEditorPart) newPart; } else if (activePart == topEditor && newPart == null) { // since we removed all the contributions, we clear the top // editor topEditor = null; } activePart = newPart; } /** * Updates the contributions given the new part as the topEditor. * * @param newEditor * the new top editor, may be <code>null</code> */ public void updateTopEditor(IEditorPart newEditor) { if (topEditor == newEditor) { return; } if (activePart == topEditor) { updateActivePart(newEditor); return; } String oldId = null; if (topEditor != null) { oldId = topEditor.getSite().getId(); } String newId = null; if (newEditor != null) { newId = newEditor.getSite().getId(); } if (oldId == null ? newId == null : oldId.equals(newId)) { // we don't have to change anything topEditor = newEditor; return; } // Remove the contributions of the old editor if (topEditor != null) { deactivateContributions(topEditor, true); } // Show (disabled) the contributions of the new editor if (newEditor != null) { activateContributions(newEditor, false); } ArrayList newActionSets = calculateActionSets(activePart, newEditor); if (!updateActionSets(newActionSets)) { updateActionBars(); } topEditor = newEditor; } /** * Activates the contributions of the given part. If <code>enable</code> * is <code>true</code> the contributions are visible and enabled, * otherwise they are disabled. * * @param part * the part whose contributions are to be activated * @param enable * <code>true</code> the contributions are to be enabled, * not just visible. */ private void activateContributions(IWorkbenchPart part, boolean enable) { PartSite site = (PartSite) part.getSite(); site.activateActionBars(enable); } /** * Deactivates the contributions of the given part. If <code>remove</code> * is <code>true</code> the contributions are removed, otherwise they * are disabled. * * @param part * the part whose contributions are to be deactivated * @param remove * <code>true</code> the contributions are to be removed, * not just disabled. */ private void deactivateContributions(IWorkbenchPart part, boolean remove) { PartSite site = (PartSite) part.getSite(); site.deactivateActionBars(remove); } /** * Calculates the action sets to show for the given part and editor * * @param part * the active part, may be <code>null</code> * @param editor * the current editor, may be <code>null</code>, may be * the active part * @return the new action sets */ private ArrayList calculateActionSets(IWorkbenchPart part, IEditorPart editor) { ArrayList newActionSets = new ArrayList(); if (part != null) { IActionSetDescriptor[] partActionSets = WorkbenchPlugin .getDefault().getActionSetRegistry().getActionSetsFor( part.getSite().getId()); for (int i = 0; i < partActionSets.length; i++) { newActionSets.add(partActionSets[i]); } } if (editor != null && editor != part) { IActionSetDescriptor[] editorActionSets = WorkbenchPlugin .getDefault().getActionSetRegistry().getActionSetsFor( editor.getSite().getId()); for (int i = 0; i < editorActionSets.length; i++) { newActionSets.add(editorActionSets[i]); } } return newActionSets; } /** * Updates the actions we are showing for the active part and current * editor. * * @param newActionSets * the action sets to show * @return <code>true</code> if the action sets changed */ private boolean updateActionSets(ArrayList newActionSets) { if (oldActionSets.equals(newActionSets)) { return false; } IContextService service = (IContextService) window .getService(IContextService.class); try { service.deferUpdates(true); // show the new for (int i = 0; i < newActionSets.size(); i++) { actionSets.showAction((IActionSetDescriptor) newActionSets .get(i)); } // hide the old for (int i = 0; i < oldActionSets.size(); i++) { actionSets.hideAction((IActionSetDescriptor) oldActionSets .get(i)); } oldActionSets = newActionSets; } finally { service.deferUpdates(false); } Perspective persp = getActivePerspective(); if (persp == null) { return false; } window.updateActionSets(); // this calls updateActionBars window.firePerspectiveChanged(WorkbenchPage.this, getPerspective(), CHANGE_ACTION_SET_SHOW); return true; } } /** * Constructs a new page with a given perspective and input. * * @param w * the parent window * @param layoutID * must not be <code>null</code> * @param input * the page input * @throws WorkbenchException * on null layout id */ public WorkbenchPage(WorkbenchWindow w, String layoutID, IAdaptable input) throws WorkbenchException { super(); if (layoutID == null) { throw new WorkbenchException(WorkbenchMessages.get().WorkbenchPage_UndefinedPerspective); } init(w, layoutID, input, true); } /** * Constructs a page. <code>restoreState(IMemento)</code> should be * called to restore this page from data stored in a persistance file. * * @param w * the parent window * @param input * the page input * @throws WorkbenchException */ public WorkbenchPage(WorkbenchWindow w, IAdaptable input) throws WorkbenchException { super(); init(w, null, input, false); } /** * Activates a part. The part will be brought to the front and given focus. * * @param part * the part to activate */ public void activate(IWorkbenchPart part) { internalActivate(part, false); } private void internalActivate(IWorkbenchPart part, boolean force) { // Sanity check. if (!certifyPart(part)) { return; } if (window.isClosing()) { return; } if (composite!=null && composite.isVisible() && !((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) { return; } // If zoomed, unzoom. zoomOutIfNecessary(part); if (part instanceof AbstractMultiEditor) { part = ((AbstractMultiEditor) part).getActiveEditor(); } // Activate part. //if (window.getActivePage() == this) { IWorkbenchPartReference ref = getReference(part); internalBringToTop(ref); setActivePart(part, force); } /** * Activates a part. The part is given focus, the pane is hilighted. */ private void activatePart(final IWorkbenchPart part) { Platform.run(new SafeRunnable(WorkbenchMessages.get().WorkbenchPage_ErrorActivatingView) { public void run() { if (part != null) { //part.setFocus(); PartPane pane = getPane(part); pane.setFocus(); PartSite site = (PartSite) part.getSite(); pane.showFocus(true); updateTabList(part); SubActionBars bars = (SubActionBars) site .getActionBars(); bars.partChanged(part); } } }); } /** * Add a fast view. */ public void addFastView(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp == null) { return; } persp.getFastViewManager().addViewReference(FastViewBar.FASTVIEWBAR_ID, -1, ref, true); } /** * Add a fast view. */ public void makeFastView(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp == null) { return; } FastViewManager fvm = persp.getFastViewManager(); if (fvm.isFastView(ref)) { return; } // Do real work. persp.makeFastView(ref); updateActivePart(); // The view is now invisible. // If it is active then deactivate it. // Notify listeners. window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_FAST_VIEW_ADD); window.firePerspectiveChanged(this, getPerspective(), CHANGE_FAST_VIEW_ADD); } /** * Adds an IPartListener to the part service. */ public void addPartListener(IPartListener l) { partList.getPartService().addPartListener(l); } /** * Adds an IPartListener to the part service. */ public void addPartListener(IPartListener2 l) { partList.getPartService().addPartListener(l); } /** * Implements IWorkbenchPage * * @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener) * @deprecated individual views should store a working set if needed and * register a property change listener directly with the * working set manager to receive notification when the view * working set is removed. */ public void addPropertyChangeListener(IPropertyChangeListener listener) { propertyChangeListeners.add(listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void addSelectionListener(ISelectionListener listener) { selectionService.addSelectionListener(listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void addSelectionListener(String partId, ISelectionListener listener) { selectionService.addSelectionListener(partId, listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void addPostSelectionListener(ISelectionListener listener) { selectionService.addPostSelectionListener(listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void addPostSelectionListener(String partId, ISelectionListener listener) { selectionService.addPostSelectionListener(partId, listener); } private ILayoutContainer getContainer(IWorkbenchPart part) { PartPane pane = getPane(part); if (pane == null) { return null; } return pane.getContainer(); } private ILayoutContainer getContainer(IWorkbenchPartReference part) { PartPane pane = getPane(part); if (pane == null) { return null; } return pane.getContainer(); } private PartPane getPane(IWorkbenchPart part) { if (part == null) { return null; } return getPane(getReference(part)); } private PartPane getPane(IWorkbenchPartReference part) { if (part == null) { return null; } return ((WorkbenchPartReference)part).getPane(); } /** * Brings a part to the front of its stack. Does not update the active part or * active editor. This should only be called if the caller knows that the part * is not in the same stack as the active part or active editor, or if the caller * is prepared to update activation after the call. * * @param part */ private boolean internalBringToTop(IWorkbenchPartReference part) { boolean broughtToTop = false; // Move part. if (part instanceof IEditorReference) { ILayoutContainer container = getContainer(part); if (container instanceof PartStack) { PartStack stack = (PartStack)container; PartPane newPart = getPane(part); if (stack.getSelection() != newPart) { stack.setSelection(newPart); } broughtToTop = true; } } else if (part instanceof IViewReference) { Perspective persp = getActivePerspective(); if (persp != null) { broughtToTop = persp.bringToTop((IViewReference)part); } } // Ensure that this part is considered the most recently activated part // in this stack activationList.bringToTop(part); return broughtToTop; } /** * Moves a part forward in the Z order of a perspective so it is visible. * If the part is in the same stack as the active part, the new part is * activated. * * @param part * the part to bring to move forward */ public void bringToTop(IWorkbenchPart part) { // Sanity check. Perspective persp = getActivePerspective(); if (persp == null || !certifyPart(part)) { return; } if (!((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) { return; } String label = null; // debugging only if (UIStats.isDebugging(UIStats.BRING_PART_TO_TOP)) { label = part != null ? part.getTitle() : "none"; //$NON-NLS-1$ } try { UIStats.start(UIStats.BRING_PART_TO_TOP, label); IWorkbenchPartReference ref = getReference(part); ILayoutContainer activeEditorContainer = getContainer(getActiveEditor()); ILayoutContainer activePartContainer = getContainer(getActivePart()); ILayoutContainer newPartContainer = getContainer(part); if (newPartContainer == activePartContainer) { makeActive(ref); } else if (newPartContainer != null && newPartContainer == activeEditorContainer) { if (ref instanceof IEditorReference) { if (part!=null) { IWorkbenchPartSite site = part.getSite(); if (site instanceof PartSite) { ref = ((PartSite) site).getPane() .getPartReference(); } } makeActiveEditor((IEditorReference)ref); } else { makeActiveEditor(null); } } else { internalBringToTop(ref); if (ref != null) { partList.firePartBroughtToTop(ref); } } } finally { UIStats.end(UIStats.BRING_PART_TO_TOP, part, label); } } /** * Resets the layout for the perspective. The active part in the old layout * is activated in the new layout for consistent user context. * * Assumes the busy cursor is active. */ private void busyResetPerspective() { ViewIntroAdapterPart introViewAdapter = ((WorkbenchIntroManager) getWorkbenchWindow() .getWorkbench().getIntroManager()).getViewIntroAdapterPart(); PartPane introPane = null; boolean introFullScreen = false; if (introViewAdapter != null) { introPane = ((PartSite) introViewAdapter.getSite()).getPane(); introViewAdapter.setHandleZoomEvents(false); introFullScreen = introPane.isZoomed(); } //try to prevent intro flicker. if (introFullScreen) { window.getShell().setRedraw(false); } try { // Always unzoom if (isZoomed()) { zoomOut(); } // Get the current perspective. // This describes the working layout of the page and differs from // the original template. Perspective oldPersp = getActivePerspective(); // Map the current perspective to the original template. // If the original template cannot be found then it has been deleted. // In that case just return. (PR#1GDSABU). IPerspectiveRegistry reg = WorkbenchPlugin.getDefault() .getPerspectiveRegistry(); PerspectiveDescriptor desc = (PerspectiveDescriptor) reg .findPerspectiveWithId(oldPersp.getDesc().getId()); if (desc == null) { desc = (PerspectiveDescriptor) reg .findPerspectiveWithId(((PerspectiveDescriptor) oldPersp .getDesc()).getOriginalId()); } if (desc == null) { return; } // Notify listeners that we are doing a reset. window.firePerspectiveChanged(this, desc, CHANGE_RESET); // Create new persp from original template. // Suppress the perspectiveOpened and perspectiveClosed events otherwise it looks like two // instances of the same perspective are open temporarily (see bug 127470). Perspective newPersp = createPerspective(desc, false); if (newPersp == null) { // We're not going through with the reset, so it is complete. window .firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); return; } // Fix for Bug 232541 [ViewMgmt] Reset Perspective ignores saveable parts. // Any view referenced from the old perspective with a ref count of // one will be closed. The following code will prompt to save. IViewReference[] oldRefs = oldPersp.getViewReferences(); List partsToClose = new ArrayList(); for (int i = 0; i < oldRefs.length; i++) { IViewReference ref = oldRefs[i]; int refCount = getViewFactory().getReferenceCount(ref); if (refCount == 1) { IWorkbenchPart actualPart = ref.getPart(false); if (actualPart != null) { partsToClose.add(actualPart); } } } SaveablesList saveablesList = null; Object postCloseInfo = null; if (partsToClose.size() > 0) { saveablesList = (SaveablesList) getWorkbenchWindow() .getService(ISaveablesLifecycleListener.class); postCloseInfo = saveablesList.preCloseParts( partsToClose, true, this.getWorkbenchWindow()); if (postCloseInfo == null) { // cancel // We're not going through with the reset, so it is // complete. window.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); return; } } // Update the perspective list and shortcut perspList.swap(oldPersp, newPersp); // Install new persp. setPerspective(newPersp); // Destroy old persp. disposePerspective(oldPersp, false); if (saveablesList != null) { saveablesList.postClose(postCloseInfo); } // Update the Coolbar layout. resetToolBarLayout(); getActionBars().getMenuManager().updateAll(true); // restore the maximized intro if (introViewAdapter != null) { try { // ensure that the intro is visible in the new perspective showView(IIntroConstants.INTRO_VIEW_ID); if (introFullScreen) { toggleZoom(introPane.getPartReference()); } } catch (PartInitException e) { WorkbenchPlugin.log("Could not restore intro", //$NON-NLS-1$ WorkbenchPlugin.getStatus(e)); } finally { // we want the intro back to a normal state before we fire the event introViewAdapter.setHandleZoomEvents(true); } } // Notify listeners that we have completed our reset. window.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); } finally { // reset the handling of zoom events (possibly for the second time) in case there was // an exception thrown if (introViewAdapter != null) { introViewAdapter.setHandleZoomEvents(true); } if (introFullScreen) { window.getShell().setRedraw(true); } } } /** * Implements <code>setPerspective</code>. * * Assumes that busy cursor is active. * * @param desc * identifies the new perspective. */ private void busySetPerspective(IPerspectiveDescriptor desc) { // Create new layout. String label = desc.getId(); // debugging only Perspective newPersp = null; try { UIStats.start(UIStats.SWITCH_PERSPECTIVE, label); PerspectiveDescriptor realDesc = (PerspectiveDescriptor) desc; newPersp = findPerspective(realDesc); if (newPersp == null) { newPersp = createPerspective(realDesc, true); if (newPersp == null) { return; } } // Change layout. setPerspective(newPersp); } finally { UIStats.end(UIStats.SWITCH_PERSPECTIVE, desc.getId(), label); } } /** * Shows a view. * * Assumes that a busy cursor is active. */ protected IViewPart busyShowView(String viewID, String secondaryID, int mode) throws PartInitException { Perspective persp = getActivePerspective(); if (persp == null) { return null; } // If this view is already visible just return. IViewReference ref = persp.findView(viewID, secondaryID); IViewPart view = null; if (ref != null) { view = ref.getView(true); } if (view != null) { busyShowView(view, mode); return view; } // Show the view. view = persp.showView(viewID, secondaryID); if (view != null) { busyShowView(view, mode); IWorkbenchPartReference partReference = getReference(view); PartPane partPane = getPane(partReference); partPane.setInLayout(true); window.firePerspectiveChanged(this, getPerspective(), partReference, CHANGE_VIEW_SHOW); window.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_SHOW); } return view; } /* * Performs showing of the view in the given mode. */ private void busyShowView(IViewPart part, int mode) { if (!((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) { return; } checkIntro(); if (mode == VIEW_ACTIVATE) { activate(part); } else if (mode == VIEW_VISIBLE) { IWorkbenchPartReference ref = getActivePartReference(); // if there is no active part or it's not a view, bring to top if (ref == null || !(ref instanceof IViewReference)) { bringToTop(part); } else { // otherwise check to see if the we're in the same stack as the active view IViewReference activeView = (IViewReference) ref; IViewReference[] viewStack = getViewReferenceStack(part); for (int i = 0; i < viewStack.length; i++) { if (viewStack[i].equals(activeView)) { return; } } bringToTop(part); } } } private void checkIntro() { IIntroManager intro = getWorkbenchWindow().getWorkbench() .getIntroManager(); IIntroPart part = intro.getIntro(); if (part == null) { return; } if (!intro.isIntroStandby(part)) { intro.setIntroStandby(part, true); } } /** * Returns whether a part exists in the current page. */ private boolean certifyPart(IWorkbenchPart part) { //Workaround for bug 22325 if (part != null && !(part.getSite() instanceof PartSite)) { return false; } if (part instanceof IEditorPart) { IEditorReference ref = (IEditorReference) getReference(part); return ref != null && getEditorManager().containsEditor(ref); } if (part instanceof IViewPart) { Perspective persp = getActivePerspective(); return persp != null && persp.containsView((IViewPart) part); } return false; } /** * Closes the perspective. */ public boolean close() { final boolean[] ret = new boolean[1]; BusyIndicator.showWhile(null, new Runnable() { public void run() { ret[0] = window.closePage(WorkbenchPage.this, true); } }); return ret[0]; } /** * See IWorkbenchPage */ public boolean closeAllSavedEditors() { // get the Saved editors IEditorReference editors[] = getEditorReferences(); IEditorReference savedEditors[] = new IEditorReference[editors.length]; int j = 0; for (int i = 0; i < editors.length; i++) { IEditorReference editor = editors[i]; if (!editor.isDirty()) { savedEditors[j++] = editor; } } //there are no unsaved editors if (j == 0) { return true; } IEditorReference[] newSaved = new IEditorReference[j]; System.arraycopy(savedEditors, 0, newSaved, 0, j); return closeEditors(newSaved, false); } /** * See IWorkbenchPage */ public boolean closeAllEditors(boolean save) { return closeEditors(getEditorReferences(), save); } private void updateActivePart() { if (isDeferred()) { return; } IWorkbenchPartReference oldActivePart = partList.getActivePartReference(); IWorkbenchPartReference oldActiveEditor = partList.getActiveEditorReference(); IWorkbenchPartReference newActivePart = null; IEditorReference newActiveEditor = null; if (!window.isClosing()) { // If an editor is active, try to keep an editor active if (oldActivePart == oldActiveEditor) { newActiveEditor = (IEditorReference)activationList.getActiveReference(true); newActivePart = newActiveEditor; if (newActivePart == null) { // Only activate a non-editor if there's no editors left newActivePart = activationList.getActiveReference(false); } } else { // If a non-editor is active, activate whatever was activated most recently newActivePart = activationList.getActiveReference(false); if (newActivePart instanceof IEditorReference) { // If that happens to be an editor, make it the active editor as well newActiveEditor = (IEditorReference)newActivePart; } else { // Otherwise, select whatever editor was most recently active newActiveEditor = (IEditorReference)activationList.getActiveReference(true); } } } if (newActiveEditor != oldActiveEditor) { makeActiveEditor(newActiveEditor); } if (newActivePart != oldActivePart) { makeActive(newActivePart); } } /** * Makes the given part active. Brings it in front if necessary. Permits null * (indicating that no part should be active). * * @param ref new active part (or null) */ private void makeActive(IWorkbenchPartReference ref) { if (ref == null) { setActivePart(null, false); } else { IWorkbenchPart newActive = ref.getPart(true); if (newActive == null) { setActivePart(null, false); } else { activate(newActive); } } } /** * Makes the given editor active. Brings it to front if necessary. Permits <code>null</code> * (indicating that no editor is active). * * @param ref the editor to make active, or <code>null</code> for no active editor */ private void makeActiveEditor(IEditorReference ref) { if (ref == getActiveEditorReference()) { return; } IEditorPart part = (ref == null) ? null : ref.getEditor(true); if (part != null) { editorMgr.setVisibleEditor(ref, false); navigationHistory.markEditor(part); } actionSwitcher.updateTopEditor(part); if (ref != null) { activationList.bringToTop(getReference(part)); } partList.setActiveEditor(ref); } /** * See IWorkbenchPage */ public boolean closeEditors(IEditorReference[] refArray, boolean save) { if (refArray.length == 0) { return true; } // Check if we're being asked to close any parts that are already closed or cannot // be closed at this time ArrayList toClose = new ArrayList(); for (int i = 0; i < refArray.length; i++) { IEditorReference reference = refArray[i]; // If we're in the middle of creating this part, this is a programming error. Abort the entire // close operation. This usually occurs if someone tries to open a dialog in a method that // isn't allowed to do so, and a *syncExec tries to close the part. If this shows up in a log // file with a dialog's event loop on the stack, then the code that opened the dialog is usually // at fault. if (reference == partBeingActivated) { WorkbenchPlugin.log(new RuntimeException("WARNING: Blocked recursive attempt to close part " //$NON-NLS-1$ + partBeingActivated.getId() + " while still in the middle of activating it")); //$NON-NLS-1$ return false; } if(reference instanceof WorkbenchPartReference) { WorkbenchPartReference ref = (WorkbenchPartReference) reference; // If we're being asked to close a part that is disposed (ie: already closed), // skip it and proceed with closing the remaining parts. if (ref.isDisposed()) { continue; } } toClose.add(reference); } IEditorReference[] editorRefs = (IEditorReference[]) toClose.toArray(new IEditorReference[toClose.size()]); // if active navigation position belongs to an editor being closed, update it // (The navigation position for an editor N was updated as an editor N + 1 // was activated. As a result, all but the last editor have up-to-date // navigation positions.) for (int i = 0; i < editorRefs.length; i++) { IEditorReference ref = editorRefs[i]; if (ref == null) continue; IEditorPart oldPart = ref.getEditor(false); if (oldPart == null) continue; if (navigationHistory.updateActive(oldPart)) break; // updated - skip the rest } // notify the model manager before the close List partsToClose = new ArrayList(); for (int i = 0; i < editorRefs.length; i++) { IEditorPart refPart = editorRefs[i].getEditor(false); if (refPart != null) { partsToClose.add(refPart); } } SaveablesList modelManager = null; Object postCloseInfo = null; if(partsToClose.size()>0) { modelManager = (SaveablesList) getWorkbenchWindow().getService(ISaveablesLifecycleListener.class); // this may prompt for saving and return null if the user canceled: postCloseInfo = modelManager.preCloseParts(partsToClose, save, getWorkbenchWindow()); if (postCloseInfo==null) { return false; } } // Fire pre-removal changes for (int i = 0; i < editorRefs.length; i++) { IEditorReference ref = editorRefs[i]; // Notify interested listeners before the close window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_CLOSE); } deferUpdates(true); try { if(modelManager!=null) { modelManager.postClose(postCloseInfo); } // Close all editors. for (int i = 0; i < editorRefs.length; i++) { IEditorReference ref = editorRefs[i]; // Remove editor from the presentation editorPresentation.closeEditor(ref); partRemoved((WorkbenchPartReference)ref); } } finally { deferUpdates(false); } // Notify interested listeners after the close window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_CLOSE); // Return true on success. return true; } /** * Enables or disables listener notifications. This is used to delay listener notifications until the * end of a public method. * * @param shouldDefer */ private void deferUpdates(boolean shouldDefer) { if (shouldDefer) { if (deferCount == 0) { startDeferring(); } deferCount++; } else { deferCount--; if (deferCount == 0) { handleDeferredEvents(); } } } private void startDeferring() { editorPresentation.getLayoutPart().deferUpdates(true); } private void handleDeferredEvents() { editorPresentation.getLayoutPart().deferUpdates(false); updateActivePart(); WorkbenchPartReference[] disposals = (WorkbenchPartReference[]) pendingDisposals.toArray(new WorkbenchPartReference[pendingDisposals.size()]); pendingDisposals.clear(); for (int i = 0; i < disposals.length; i++) { WorkbenchPartReference reference = disposals[i]; disposePart(reference); } } private boolean isDeferred() { return deferCount > 0; } /** * See IWorkbenchPage#closeEditor */ public boolean closeEditor(IEditorReference editorRef, boolean save) { return closeEditors(new IEditorReference[] {editorRef}, save); } /** * See IWorkbenchPage#closeEditor */ public boolean closeEditor(IEditorPart editor, boolean save) { IWorkbenchPartReference ref = getReference(editor); if (ref instanceof IEditorReference) { return closeEditors(new IEditorReference[] {(IEditorReference) ref}, save); } return false; } /** * @see IWorkbenchPage#closePerspective(IPerspectiveDescriptor, boolean, boolean) */ public void closePerspective(IPerspectiveDescriptor desc, boolean saveParts, boolean closePage) { Perspective persp = findPerspective(desc); if (persp != null) { closePerspective(persp, saveParts, closePage); } } /** * Closes the specified perspective in this page. If this is not the last * perspective in the page, and it is active, then the perspective specified by * <code>descToActivate</code> will be activated. If the last perspective in * this page is closed, then all editors are closed. Views that are not shown * in other perspectives are closed as well. If <code>saveParts</code> is * <code>true</code>, the user will be prompted to save any unsaved changes * for parts that are being closed. The page itself is closed if * <code>closePage</code> is <code>true</code>. * * @param desc * the descriptor of the perspective to be closed * @param descToActivate * the descriptor of the perspective to activate * @param saveParts * whether the page's parts should be saved if closed * @param closePage * whether the page itself should be closed if last perspective * @since 3.4 */ public void closePerspective(IPerspectiveDescriptor desc, IPerspectiveDescriptor descToActivate, boolean saveParts, boolean closePage) { Perspective persp = findPerspective(desc); Perspective perspToActivate = findPerspective(descToActivate); if (persp != null) { closePerspective(persp, perspToActivate, saveParts, closePage); } } /** * Closes the specified perspective. If last perspective, then entire page * is closed. * * @param persp * the perspective to be closed * @param saveParts * whether the parts that are being closed should be saved * (editors if last perspective, views if not shown in other * parspectives) */ /* package */ void closePerspective(Perspective persp, boolean saveParts, boolean closePage) { closePerspective(persp, null, saveParts, closePage); } /** * Closes the specified perspective. If last perspective, then entire page * is closed. * * @param persp * the perspective to be closed * @param perspToActivate * the perspective to activate * @param saveParts * whether the parts that are being closed should be saved * (editors if last perspective, views if not shown in other * parspectives) */ /* package */ void closePerspective(Perspective persp, Perspective perspToActivate, boolean saveParts, boolean closePage) { // Always unzoom if (isZoomed()) { zoomOut(); } List partsToSave = new ArrayList(); List viewsToClose = new ArrayList(); // collect views that will go away and views that are dirty IViewReference[] viewReferences = persp.getViewReferences(); for (int i = 0; i < viewReferences.length; i++) { IViewReference reference = viewReferences[i]; if (getViewFactory().getReferenceCount(reference) == 1) { IViewPart viewPart = reference.getView(false); if (viewPart != null) { viewsToClose.add(viewPart); if (saveParts && reference.isDirty()) { partsToSave.add(viewPart); } } } } if (saveParts && perspList.size() == 1) { // collect editors that are dirty IEditorReference[] editorReferences = getEditorReferences(); for (int i = 0; i < editorReferences.length; i++) { IEditorReference reference = editorReferences[i]; if (reference.isDirty()) { IEditorPart editorPart = reference.getEditor(false); if (editorPart != null) { partsToSave.add(editorPart); } } } } if (saveParts && !partsToSave.isEmpty()) { if (!EditorManager.saveAll(partsToSave, true, true, false, window)) { // user canceled return; } } // Close all editors on last perspective close if (perspList.size() == 1 && getEditorManager().getEditorCount() > 0) { // Close all editors if (!closeAllEditors(false)) { return; } } // closeAllEditors already notified the saveables list about the editors. SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class); // we took care of the saving already, so pass in false (postCloseInfo will be non-null) Object postCloseInfo = saveablesList.preCloseParts(viewsToClose, false, getWorkbenchWindow()); saveablesList.postClose(postCloseInfo); // Dispose of the perspective boolean isActive = (perspList.getActive() == persp); if (isActive) { if (perspToActivate != null) { setPerspective(perspToActivate); } else { setPerspective(perspList.getNextActive()); } } disposePerspective(persp, true); if (closePage && perspList.size() == 0) { close(); } } /** * Forces all perspectives on the page to zoom out. */ public void unzoomAllPerspectives() { for (Iterator perspIter = perspList.iterator(); perspIter.hasNext();) { Perspective persp = (Perspective) perspIter.next(); persp.getPresentation().forceNoZoom(); } } /** * @see IWorkbenchPage#closeAllPerspectives(boolean, boolean) */ public void closeAllPerspectives(boolean saveEditors, boolean closePage) { if (perspList.isEmpty()) { return; } // Always unzoom if (isZoomed()) { zoomOut(); } if(saveEditors) { // directly call to the editor manager that we're saving and closing // parts, see bug 272070 if (!getEditorManager().saveAll(true, true, false)) { return; } } // Close all editors if (!closeAllEditors(false)) { return; } // Deactivate the active perspective and part setPerspective((Perspective) null); // Close each perspective in turn PerspectiveList oldList = perspList; perspList = new PerspectiveList(); Iterator itr = oldList.iterator(); while (itr.hasNext()) { closePerspective((Perspective) itr.next(), false, false); } if (closePage) { close(); } } /** * Creates the client composite. */ private void createClientComposite() { final Composite parent = window.getPageComposite(); StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() { composite = new Composite(parent, SWT.NONE); composite.setVisible(false); // Make visible on activate. // force the client composite to be layed out parent.layout(); } }); } /** * Creates a new view set. Return null on failure. * * @param desc the perspective descriptor * @param notify whether to fire a perspective opened event */ private Perspective createPerspective(PerspectiveDescriptor desc, boolean notify) { String label = desc.getId(); // debugging only try { UIStats.start(UIStats.CREATE_PERSPECTIVE, label); Perspective persp = ((WorkbenchImplementation) Tweaklets .get(WorkbenchImplementation.KEY)).createPerspective(desc, this); perspList.add(persp); if (notify) { window.firePerspectiveOpened(this, desc); } //if the perspective is fresh and uncustomzied then it is not dirty //no reset will be prompted for if (!desc.hasCustomDefinition()) { dirtyPerspectives.remove(desc.getId()); } return persp; } catch (WorkbenchException e) { if (!((Workbench) window.getWorkbench()).isStarting()) { MessageDialog .openError( window.getShell(), WorkbenchMessages.get().Error, NLS.bind(WorkbenchMessages.get().Workbench_showPerspectiveError,desc.getId() )); } return null; } finally { UIStats.end(UIStats.CREATE_PERSPECTIVE, desc.getId(), label); } } /** * This is called by child objects after a part has been added to the page. * The page will in turn notify its listeners. */ /* package */ void partAdded(WorkbenchPartReference ref) { activationList.add(ref); partList.addPart(ref); updateActivePart(); } /** * This is called by child objects after a part has been added to the page. * The part will be queued for disposal after all listeners have been notified */ /* package */ void partRemoved(WorkbenchPartReference ref) { activationList.remove(ref); disposePart(ref); } private void disposePart(WorkbenchPartReference ref) { if (isDeferred()) { pendingDisposals.add(ref); } else { partList.removePart(ref); ref.dispose(); } } /** * Deactivates a part. The pane is unhilighted. */ private void deactivatePart(IWorkbenchPart part) { if (part != null) { PartSite site = (PartSite) part.getSite(); site.getPane().showFocus(false); } } /** * Detaches a view from the WorkbenchWindow. */ public void detachView(IViewReference ref){ Perspective persp = getActivePerspective(); if(persp == null) { return; } // RAP [rh] PerspectiveHelper#detachPart not implemented // PerspectiveHelper presentation = persp.getPresentation(); // presentation.detachPart(ref); } /** * Removes a detachedwindow. */ public void attachView(IViewReference ref){ PerspectiveHelper presentation = getPerspectivePresentation(); presentation.attachPart(ref); } /** * Cleanup. */ public void dispose() { // Always unzoom if (isZoomed()) { zoomOut(); } makeActiveEditor(null); makeActive(null); // Close and dispose the editors. closeAllEditors(false); // Need to make sure model data is cleaned up when the page is // disposed. Collect all the views on the page and notify the // saveable list of a pre/post close. This will free model data. IWorkbenchPartReference[] partsToClose = getOpenParts(); List dirtyParts = new ArrayList(partsToClose.length); for (int i = 0; i < partsToClose.length; i++) { IWorkbenchPart part = partsToClose[i].getPart(false); if (part != null && part instanceof IViewPart) { dirtyParts.add(part); } } SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class); Object postCloseInfo = saveablesList.preCloseParts(dirtyParts, false,getWorkbenchWindow()); saveablesList.postClose(postCloseInfo); // Get rid of perspectives. This will close the views. Iterator itr = perspList.iterator(); while (itr.hasNext()) { Perspective perspective = (Perspective) itr.next(); window.firePerspectiveClosed(this, perspective.getDesc()); perspective.dispose(); } perspList = new PerspectiveList(); // Capture views. IViewReference refs[] = viewFactory.getViews(); if (refs.length > 0) { // Dispose views. for (int i = 0; i < refs.length; i++) { final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i]; //partList.removePart(ref); //firePartClosed(refs[i]); Platform.run(new SafeRunnable() { public void run() { // WorkbenchPlugin.log(new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH, // Status.OK, "WorkbenchPage leaked a refcount for view " + ref.getId(), null)); //$NON-NLS-1$//$NON-NLS-2$ ref.dispose(); } public void handleException(Throwable e) { } }); } } activationList = new ActivationList(); // Get rid of editor presentation. editorPresentation.dispose(); // Get rid of composite. composite.dispose(); navigationHistory.dispose(); stickyViewMan.clear(); if (tracker != null) { tracker.close(); } // if we're destroying a window in a non-shutdown situation then we should // clean up the working set we made. if (!window.getWorkbench().isClosing()) { if (aggregateWorkingSet != null) { PlatformUI.getWorkbench().getWorkingSetManager().removeWorkingSet(aggregateWorkingSet); } } } /** * Dispose a perspective. * * @param persp the perspective descriptor * @param notify whether to fire a perspective closed event */ private void disposePerspective(Perspective persp, boolean notify) { // Get rid of perspective. perspList.remove(persp); if (notify) { window.firePerspectiveClosed(this, persp.getDesc()); } persp.dispose(); stickyViewMan.remove(persp.getDesc().getId()); } /** * @return NavigationHistory */ public INavigationHistory getNavigationHistory() { return navigationHistory; } /** * Edits the action sets. */ public boolean editActionSets() { Perspective persp = getActivePerspective(); if (persp == null) { return false; } // Create list dialog. CustomizePerspectiveDialog dlg = window.createCustomizePerspectiveDialog(persp); // Open. boolean ret = (dlg.open() == Window.OK); if (ret) { window.updateActionSets(); window.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET); window.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET_COMPLETE); } return ret; } /** * Returns the first view manager with given ID. */ public Perspective findPerspective(IPerspectiveDescriptor desc) { Iterator itr = perspList.iterator(); while (itr.hasNext()) { Perspective mgr = (Perspective) itr.next(); if (desc.getId().equals(mgr.getDesc().getId())) { return mgr; } } return null; } /** * See IWorkbenchPage@findView. */ public IViewPart findView(String id) { IViewReference ref = findViewReference(id); if (ref == null) { return null; } return ref.getView(true); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage */ public IViewReference findViewReference(String viewId) { return findViewReference(viewId, null); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage */ public IViewReference findViewReference(String viewId, String secondaryId) { Perspective persp = getActivePerspective(); if (persp == null) { return null; } return persp.findView(viewId, secondaryId); } /** * Notify property change listeners about a property change. * * @param changeId * the change id * @param oldValue * old property value * @param newValue * new property value */ private void firePropertyChange(String changeId, Object oldValue, Object newValue) { UIListenerLogging.logPagePropertyChanged(this, changeId, oldValue, newValue); Object[] listeners = propertyChangeListeners.getListeners(); PropertyChangeEvent event = new PropertyChangeEvent(this, changeId, oldValue, newValue); for (int i = 0; i < listeners.length; i++) { ((IPropertyChangeListener) listeners[i]).propertyChange(event); } } /* * Returns the action bars. */ public IActionBars getActionBars() { if (actionBars == null) { actionBars = new WWinActionBars(window); } return actionBars; } /** * Returns an array of the visible action sets. */ public IActionSetDescriptor[] getActionSets() { Collection collection = actionSets.getVisibleItems(); return (IActionSetDescriptor[]) collection.toArray(new IActionSetDescriptor[collection.size()]); } /** * @see IWorkbenchPage */ public IEditorPart getActiveEditor() { return partList.getActiveEditor(); } /** * Returns the reference for the active editor, or <code>null</code> * if there is no active editor. * * @return the active editor reference or <code>null</code> */ public IEditorReference getActiveEditorReference() { return partList.getActiveEditorReference(); } /* * (non-Javadoc) Method declared on IPartService */ public IWorkbenchPart getActivePart() { return partList.getActivePart(); } /* * (non-Javadoc) Method declared on IPartService */ public IWorkbenchPartReference getActivePartReference() { return partList.getActivePartReference(); } /** * Returns the active perspective for the page, <code>null</code> if * none. */ public Perspective getActivePerspective() { return perspList.getActive(); } /** * Returns the client composite. */ public Composite getClientComposite() { return composite; } // for dynamic UI - change access from private to protected // for testing purposes only, changed from protected to public /** * Answer the editor manager for this window. */ public EditorManager getEditorManager() { return editorMgr; } /** * Answer the perspective presentation. */ public PerspectiveHelper getPerspectivePresentation() { if (getActivePerspective() != null) { return getActivePerspective().getPresentation(); } return null; } /** * Answer the editor presentation. */ public EditorAreaHelper getEditorPresentation() { return editorPresentation; } /** * See IWorkbenchPage. */ public IEditorPart[] getEditors() { final IEditorReference refs[] = getEditorReferences(); final ArrayList result = new ArrayList(refs.length); Display d = getWorkbenchWindow().getShell().getDisplay(); //Must be backward compatible. d.syncExec(new Runnable() { public void run() { for (int i = 0; i < refs.length; i++) { IWorkbenchPart part = refs[i].getPart(true); if (part != null) { result.add(part); } } } }); final IEditorPart editors[] = new IEditorPart[result.size()]; return (IEditorPart[]) result.toArray(editors); } public IEditorPart[] getDirtyEditors() { return getEditorManager().getDirtyEditors(); } public ISaveablePart[] getDirtyParts() { List result = new ArrayList(3); IWorkbenchPartReference[] allParts = getAllParts(); for (int i = 0; i < allParts.length; i++) { IWorkbenchPartReference reference = allParts[i]; IWorkbenchPart part = reference.getPart(false); if (part != null && part instanceof ISaveablePart) { ISaveablePart saveable = (ISaveablePart)part; if (saveable.isDirty()) { result.add(saveable); } } } return (ISaveablePart[]) result.toArray(new ISaveablePart[result.size()]); } /** * See IWorkbenchPage. */ public IEditorPart findEditor(IEditorInput input) { return getEditorManager().findEditor(input); } /** * See IWorkbenchPage. */ public IEditorReference[] findEditors(IEditorInput input, String editorId, int matchFlags) { return getEditorManager().findEditors(input, editorId, matchFlags); } /** * See IWorkbenchPage. */ public IEditorReference[] getEditorReferences() { return editorPresentation.getEditors(); } /** * Returns the docked views. */ public IViewReference[] getFastViews() { Perspective persp = getActivePerspective(); if (persp != null) { return persp.getFastViews(); } else { return new IViewReference[0]; } } /** * @see IWorkbenchPage */ public IAdaptable getInput() { return input; } /** * Returns the page label. This is a combination of the page input and * active perspective. */ public String getLabel() { String label = WorkbenchMessages.get().WorkbenchPage_UnknownLabel; IWorkbenchAdapter adapter = (IWorkbenchAdapter) Util.getAdapter(input, IWorkbenchAdapter.class); if (adapter != null) { label = adapter.getLabel(input); } Perspective persp = getActivePerspective(); if (persp != null) { label = NLS.bind(WorkbenchMessages.get().WorkbenchPage_PerspectiveFormat, label, persp.getDesc().getLabel()); } else if (deferredActivePersp != null) { label = NLS.bind(WorkbenchMessages.get().WorkbenchPage_PerspectiveFormat,label, deferredActivePersp.getLabel()); } return label; } /** * Returns the perspective. */ public IPerspectiveDescriptor getPerspective() { if (deferredActivePersp != null) { return deferredActivePersp; } Perspective persp = getActivePerspective(); if (persp != null) { return persp.getDesc(); } else { return null; } } /* * (non-Javadoc) Method declared on ISelectionService */ public ISelection getSelection() { return selectionService.getSelection(); } /* * (non-Javadoc) Method declared on ISelectionService */ public ISelection getSelection(String partId) { return selectionService.getSelection(partId); } /** * Returns the ids of the parts to list in the Show In... prompter. This is * a List of Strings. */ public ArrayList getShowInPartIds() { Perspective persp = getActivePerspective(); if (persp != null) { return persp.getShowInPartIds(); } else { return new ArrayList(); } } /** * The user successfully performed a Show In... action on the specified * part. Update the list of Show In items accordingly. */ public void performedShowIn(String partId) { Perspective persp = getActivePerspective(); if (persp != null) { persp.performedShowIn(partId); } } /** * Sorts the given collection of show in target part ids in MRU order. */ public void sortShowInPartIds(ArrayList partIds) { final Perspective persp = getActivePerspective(); if (persp != null) { Collections.sort(partIds, new Comparator() { public int compare(Object a, Object b) { long ta = persp.getShowInTime((String) a); long tb = persp.getShowInTime((String) b); return (ta == tb) ? 0 : ((ta > tb) ? -1 : 1); } }); } } /* * Returns the view factory. */ public ViewFactory getViewFactory() { if (viewFactory == null) { viewFactory = new ViewFactory(this, WorkbenchPlugin.getDefault() .getViewRegistry()); } return viewFactory; } /** * See IWorkbenchPage. */ public IViewReference[] getViewReferences() { Perspective persp = getActivePerspective(); if (persp != null) { return persp.getViewReferences(); } else { return new IViewReference[0]; } } /** * See IWorkbenchPage. */ public IViewPart[] getViews() { return getViews(null, true); } /** * Returns all view parts in the specified perspective * * @param persp the perspective * @return an array of view parts */ /*package*/IViewPart[] getViews(Perspective persp, boolean restore) { if (persp == null) { persp = getActivePerspective(); } if (persp != null) { IViewReference refs[] = persp.getViewReferences(); ArrayList parts = new ArrayList(refs.length); for (int i = 0; i < refs.length; i++) { IWorkbenchPart part = refs[i].getPart(restore); if (part != null) { parts.add(part); } } IViewPart[] result = new IViewPart[parts.size()]; return (IViewPart[]) parts.toArray(result); } return new IViewPart[0]; } /** * See IWorkbenchPage. */ public IWorkbenchWindow getWorkbenchWindow() { return window; } /** * Implements IWorkbenchPage * * @see org.eclipse.ui.IWorkbenchPage#getWorkingSet() * @deprecated individual views should store a working set if needed */ public IWorkingSet getWorkingSet() { return workingSet; } /** * @see IWorkbenchPage */ public void hideActionSet(String actionSetID) { Perspective persp = getActivePerspective(); if (persp != null) { persp.removeActionSet(actionSetID); window.updateActionSets(); window.firePerspectiveChanged(this, getPerspective(), CHANGE_ACTION_SET_HIDE); } } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage#hideView(org.eclipse.ui.IViewReference) */ public void hideView(IViewReference ref) { // Sanity check. if (ref == null) { return; } Perspective persp = getActivePerspective(); if (persp == null) { return; } boolean promptedForSave = false; IViewPart view = ref.getView(false); if (view != null) { if (!certifyPart(view)) { return; } // Confirm. if (view instanceof ISaveablePart) { ISaveablePart saveable = (ISaveablePart)view; if (saveable.isSaveOnCloseNeeded()) { IWorkbenchWindow window = view.getSite().getWorkbenchWindow(); boolean success = EditorManager.saveAll(Collections.singletonList(view), true, true, false, window); if (!success) { // the user cancelled. return; } promptedForSave = true; } } } int refCount = getViewFactory().getReferenceCount(ref); SaveablesList saveablesList = null; Object postCloseInfo = null; if (refCount == 1) { IWorkbenchPart actualPart = ref.getPart(false); if (actualPart != null) { saveablesList = (SaveablesList) actualPart .getSite().getService(ISaveablesLifecycleListener.class); postCloseInfo = saveablesList.preCloseParts(Collections .singletonList(actualPart), !promptedForSave, this .getWorkbenchWindow()); if (postCloseInfo==null) { // cancel return; } } } // Notify interested listeners before the hide window.firePerspectiveChanged(this, persp.getDesc(), ref, CHANGE_VIEW_HIDE); PartPane pane = getPane(ref); pane.setInLayout(false); updateActivePart(); if (saveablesList != null) { saveablesList.postClose(postCloseInfo); } // Hide the part. persp.hideView(ref); // Notify interested listeners after the hide window.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_HIDE); } /* package */void refreshActiveView() { updateActivePart(); } /** * See IPerspective */ public void hideView(IViewPart view) { hideView((IViewReference)getReference(view)); } /** * Initialize the page. * * @param w * the parent window * @param layoutID * may be <code>null</code> if restoring from file * @param input * the page input * @param openExtras * whether to process the perspective extras preference */ private void init(WorkbenchWindow w, String layoutID, IAdaptable input, boolean openExtras) throws WorkbenchException { // Save args. this.window = w; this.input = input; actionSets = new ActionSetManager(w); // Create presentation. createClientComposite(); editorPresentation = new EditorAreaHelper(this); editorMgr = new EditorManager(window, this, editorPresentation); // add this page as a client to be notified when the UI has re-orded perspectives // so that the order can be properly maintained in the receiver. // E.g. a UI might support drag-and-drop and will need to make this known to ensure // #saveState and #restoreState do not lose this re-ordering w.addPerspectiveReorderListener(new IReorderListener() { public void reorder(Object perspective, int newLoc) { perspList.reorder((IPerspectiveDescriptor)perspective, newLoc); } }); if (openExtras) { openPerspectiveExtras(); } // Get perspective descriptor. if (layoutID != null) { PerspectiveDescriptor desc = (PerspectiveDescriptor) WorkbenchPlugin .getDefault().getPerspectiveRegistry() .findPerspectiveWithId(layoutID); if (desc == null) { throw new WorkbenchException( NLS.bind(WorkbenchMessages.get().WorkbenchPage_ErrorCreatingPerspective,layoutID )); } Perspective persp = findPerspective(desc); if (persp == null) { persp = createPerspective(desc, true); } perspList.setActive(persp); window.firePerspectiveActivated(this, desc); } getExtensionTracker() .registerHandler( perspectiveChangeHandler, ExtensionTracker .createExtensionPointFilter(getPerspectiveExtensionPoint())); } /** * Opens the perspectives specified in the PERSPECTIVE_BAR_EXTRAS preference (see bug 84226). */ public void openPerspectiveExtras() { String extras = PrefUtil.getAPIPreferenceStore().getString( IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS); StringTokenizer tok = new StringTokenizer(extras, ", "); //$NON-NLS-1$ ArrayList descs = new ArrayList(); while (tok.hasMoreTokens()) { String id = tok.nextToken(); IPerspectiveDescriptor desc = WorkbenchPlugin.getDefault().getPerspectiveRegistry().findPerspectiveWithId(id); if (desc != null) { descs.add(desc); } } // HACK: The perspective switcher currently adds the button for a new perspective to the beginning of the list. // So, we process the extra perspectives in reverse order here to have their buttons appear in the order declared. for (int i = descs.size(); --i >= 0;) { PerspectiveDescriptor desc = (PerspectiveDescriptor) descs.get(i); if (findPerspective(desc) == null) { createPerspective(desc, true); } } } /** * See IWorkbenchPage. */ public boolean isPartVisible(IWorkbenchPart part) { PartPane pane = getPane(part); return pane != null && pane.getVisible(); } /** * See IWorkbenchPage. */ public boolean isEditorAreaVisible() { Perspective persp = getActivePerspective(); if (persp == null) { return false; } return persp.isEditorAreaVisible(); } /** * Returns whether the view is fast. */ public boolean isFastView(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp != null) { return persp.isFastView(ref); } else { return false; } } /** * Return whether the view is closeable or not. * * @param ref the view reference to check. Must not be <code>null</code>. * @return true if the part is closeable. */ public boolean isCloseable(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp != null) { return persp.isCloseable(ref); } return false; } /** * Return whether the view is moveable or not. * * @param ref the view reference to check. Must not be <code>null</code>. * @return true if the part is moveable. */ public boolean isMoveable(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp != null) { return persp.isMoveable(ref); } return false; } /** * Returns whether the layout of the active * perspective is fixed. */ public boolean isFixedLayout() { Perspective persp = getActivePerspective(); if (persp != null) { return persp.isFixedLayout(); } else { return false; } } /** * Return the active fast view or null if there are no fast views or if * there are all minimized. */ public IViewReference getActiveFastView() { Perspective persp = getActivePerspective(); if (persp != null) { return persp.getActiveFastView(); } else { return null; } } /** * Return true if the perspective has a dirty editor. */ protected boolean isSaveNeeded() { return getEditorManager().isSaveAllNeeded(); } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPage#isPageZoomed() */ public boolean isPageZoomed() { Perspective persp = getActivePerspective(); if (persp == null) { return false; } if (persp.getPresentation() == null) { return false; } if (Perspective.useNewMinMax(persp)) return persp.getPresentation().getMaximizedStack() != null; // Default to the legacy code return isZoomed(); } /** * Returns whether the page is zoomed. * @return <code>true</code> if the page is zoomed. * * <strong>NOTE:</strong> As of 3.3 this method should always return 'false' * when using the new min/max behavior. It is only used for * legacy 'zoom' handling. * */ public boolean isZoomed() { Perspective persp = getActivePerspective(); if (persp == null) { return false; } if (persp.getPresentation() == null) { return false; } return persp.getPresentation().isZoomed(); } /** * This method is called when the page is activated. */ protected void onActivate() { composite.setVisible(true); Perspective persp = getActivePerspective(); if (persp != null) { persp.onActivate(); updateVisibility(null, persp); } } /** * This method is called when the page is deactivated. */ protected void onDeactivate() { makeActiveEditor(null); makeActive(null); if (getActivePerspective() != null) { getActivePerspective().onDeactivate(); } composite.setVisible(false); } /** * See IWorkbenchPage. */ public void reuseEditor(IReusableEditor editor, IEditorInput input) { // Rather than calling editor.setInput on the editor directly, we do it through the part reference. // This case lets us detect badly behaved editors that are not firing a PROP_INPUT event in response // to the input change... but if all editors obeyed their API contract, the "else" branch would be // sufficient. IWorkbenchPartReference ref = getReference(editor); if (ref instanceof EditorReference) { EditorReference editorRef = (EditorReference) ref; editorRef.setInput(input); } else { editor.setInput(input); } navigationHistory.markEditor(editor); } /** * See IWorkbenchPage. */ public IEditorPart openEditor(IEditorInput input, String editorID) throws PartInitException { return openEditor(input, editorID, true, MATCH_INPUT); } /** * See IWorkbenchPage. */ public IEditorPart openEditor(IEditorInput input, String editorID, boolean activate) throws PartInitException { return openEditor(input, editorID, activate, MATCH_INPUT); } /** * See IWorkbenchPage. */ public IEditorPart openEditor(final IEditorInput input, final String editorID, final boolean activate, final int matchFlags) throws PartInitException { return openEditor(input, editorID, activate, matchFlags, null); } /** * This is not public API but for use internally. editorState can be <code>null</code>. */ public IEditorPart openEditor(final IEditorInput input, final String editorID, final boolean activate, final int matchFlags, final IMemento editorState) throws PartInitException { if (input == null || editorID == null) { throw new IllegalArgumentException(); } final IEditorPart result[] = new IEditorPart[1]; final PartInitException ex[] = new PartInitException[1]; BusyIndicator.showWhile(window.getWorkbench().getDisplay(), new Runnable() { public void run() { try { result[0] = busyOpenEditor(input, editorID, activate, matchFlags, editorState); } catch (PartInitException e) { ex[0] = e; } } }); if (ex[0] != null) { throw ex[0]; } return result[0]; } /* * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program. * Opens a new editor using the given input and descriptor. (Normally, editors are opened using * an editor ID and an input.) */ public IEditorPart openEditorFromDescriptor(final IEditorInput input, final IEditorDescriptor editorDescriptor, final boolean activate, final IMemento editorState) throws PartInitException { if (input == null || !(editorDescriptor instanceof EditorDescriptor)) { throw new IllegalArgumentException(); } final IEditorPart result[] = new IEditorPart[1]; final PartInitException ex[] = new PartInitException[1]; BusyIndicator.showWhile(window.getWorkbench().getDisplay(), new Runnable() { public void run() { try { result[0] = busyOpenEditorFromDescriptor(input, (EditorDescriptor)editorDescriptor, activate, editorState); } catch (PartInitException e) { ex[0] = e; } } }); if (ex[0] != null) { throw ex[0]; } return result[0]; } /** * @see #openEditor(IEditorInput, String, boolean, int) */ private IEditorPart busyOpenEditor(IEditorInput input, String editorID, boolean activate, int matchFlags, IMemento editorState) throws PartInitException { final Workbench workbench = (Workbench) getWorkbenchWindow() .getWorkbench(); workbench.largeUpdateStart(); try { return busyOpenEditorBatched(input, editorID, activate, matchFlags, editorState); } finally { workbench.largeUpdateEnd(); } } /* * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program. * See openEditorFromDescriptor(). */ private IEditorPart busyOpenEditorFromDescriptor(IEditorInput input, EditorDescriptor editorDescriptor, boolean activate, IMemento editorState) throws PartInitException { final Workbench workbench = (Workbench) getWorkbenchWindow() .getWorkbench(); workbench.largeUpdateStart(); try { return busyOpenEditorFromDescriptorBatched(input, editorDescriptor, activate, editorState); } finally { workbench.largeUpdateEnd(); } } /** * Do not call this method. Use <code>busyOpenEditor</code>. * * @see IWorkbenchPage#openEditor(IEditorInput, String, boolean) */ protected IEditorPart busyOpenEditorBatched(IEditorInput input, String editorID, boolean activate, int matchFlags, IMemento editorState) throws PartInitException { // If an editor already exists for the input, use it. IEditorPart editor = null; // Reuse an existing open editor, unless we are in "new editor tab management" mode editor = getEditorManager().findEditor(editorID, input, ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getReuseEditorMatchFlags(matchFlags)); if (editor != null) { if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID.equals(editorID)) { if (editor.isDirty()) { MessageDialog dialog = new MessageDialog( getWorkbenchWindow().getShell(), WorkbenchMessages.get().Save, null, // accept the default window icon NLS.bind(WorkbenchMessages.get().WorkbenchPage_editorAlreadyOpenedMsg, input.getName()), MessageDialog.QUESTION, new String[] { IDialogConstants.get().YES_LABEL, IDialogConstants.get().NO_LABEL, IDialogConstants.get().CANCEL_LABEL }, 0) { protected int getShellStyle() { return super.getShellStyle() | SWT.SHEET; } }; int saveFile = dialog.open(); if (saveFile == 0) { try { final IEditorPart editorToSave = editor; getWorkbenchWindow().run(false, false, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { editorToSave.doSave(monitor); } }); } catch (InvocationTargetException e) { throw (RuntimeException) e.getTargetException(); } catch (InterruptedException e) { return null; } } else if (saveFile == 2) { return null; } } } else { // do the IShowEditorInput notification before showing the editor // to reduce flicker if (editor instanceof IShowEditorInput) { ((IShowEditorInput) editor).showEditorInput(input); } showEditor(activate, editor); return editor; } } // Otherwise, create a new one. This may cause the new editor to // become the visible (i.e top) editor. IEditorReference ref = null; try { partBeingOpened = true; ref = getEditorManager().openEditor(editorID, input, true, editorState); if (ref != null) { editor = ref.getEditor(true); } } finally { partBeingOpened = false; } if (editor != null) { setEditorAreaVisible(true); if (activate) { if (editor instanceof AbstractMultiEditor) { activate(((AbstractMultiEditor) editor).getActiveEditor()); } else { activate(editor); } } else { bringToTop(editor); } window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_OPEN); window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); } return editor; } /* * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program. * See openEditorFromDescriptor(). */ private IEditorPart busyOpenEditorFromDescriptorBatched(IEditorInput input, EditorDescriptor editorDescriptor, boolean activate, IMemento editorState) throws PartInitException { IEditorPart editor = null; // Create a new one. This may cause the new editor to // become the visible (i.e top) editor. IEditorReference ref = null; ref = getEditorManager().openEditorFromDescriptor(editorDescriptor, input, editorState); if (ref != null) { editor = ref.getEditor(true); } if (editor != null) { setEditorAreaVisible(true); if (activate) { if (editor instanceof AbstractMultiEditor) { activate(((AbstractMultiEditor) editor).getActiveEditor()); } else { activate(editor); } } else { bringToTop(editor); } window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_OPEN); window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); } return editor; } public void openEmptyTab() { IEditorPart editor = null; EditorReference ref = null; ref = (EditorReference) getEditorManager().openEmptyTab(); if (ref != null) { editor = ref.getEmptyEditor((EditorDescriptor) ((EditorRegistry) WorkbenchPlugin .getDefault().getEditorRegistry()) .findEditor(EditorRegistry.EMPTY_EDITOR_ID)); } if (editor != null) { setEditorAreaVisible(true); activate(editor); window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_OPEN); window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); } } protected void showEditor(boolean activate, IEditorPart editor) { setEditorAreaVisible(true); if (activate) { zoomOutIfNecessary(editor); activate(editor); } else { bringToTop(editor); } } /** * See IWorkbenchPage. */ public boolean isEditorPinned(IEditorPart editor) { WorkbenchPartReference ref = (WorkbenchPartReference)getReference(editor); return ref != null && ref.isPinned(); } /** * Returns whether changes to a part will affect zoom. There are a few * conditions for this .. - we are zoomed. - the part is contained in the * main window. - the part is not the zoom part - the part is not a fast * view - the part and the zoom part are not in the same editor workbook */ private boolean partChangeAffectsZoom(IWorkbenchPartReference ref) { PartPane pane = ((WorkbenchPartReference) ref).getPane(); if (pane instanceof MultiEditorInnerPane) { pane = ((MultiEditorInnerPane) pane).getParentPane(); } return getActivePerspective().getPresentation().partChangeAffectsZoom( pane); } /** * Removes a fast view. */ public void removeFastView(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp == null) { return; } // Do real work. persp.removeFastView(ref); // Notify listeners. window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_FAST_VIEW_REMOVE); window.firePerspectiveChanged(this, getPerspective(), CHANGE_FAST_VIEW_REMOVE); } /** * Removes an IPartListener from the part service. */ public void removePartListener(IPartListener l) { partList.getPartService().removePartListener(l); } /** * Removes an IPartListener from the part service. */ public void removePartListener(IPartListener2 l) { partList.getPartService().removePartListener(l); } /** * Implements IWorkbenchPage * * @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener) * @deprecated individual views should store a working set if needed and * register a property change listener directly with the * working set manager to receive notification when the view * working set is removed. */ public void removePropertyChangeListener(IPropertyChangeListener listener) { propertyChangeListeners.remove(listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void removeSelectionListener(ISelectionListener listener) { selectionService.removeSelectionListener(listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void removeSelectionListener(String partId, ISelectionListener listener) { selectionService.removeSelectionListener(partId, listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void removePostSelectionListener(ISelectionListener listener) { selectionService.removePostSelectionListener(listener); } /* * (non-Javadoc) Method declared on ISelectionListener. */ public void removePostSelectionListener(String partId, ISelectionListener listener) { selectionService.removePostSelectionListener(partId, listener); } /** * This method is called when a part is activated by clicking within it. In * response, the part, the pane, and all of its actions will be activated. * <p> * In the current design this method is invoked by the part pane when the * pane, the part, or any children gain focus. * </p><p> * If creating the part causes a forceFocus() well ignore this * activation request. * </p> */ public void requestActivation(IWorkbenchPart part) { // Sanity check. if (!certifyPart(part) || partBeingOpened) { return; } if (part instanceof AbstractMultiEditor) { part = ((AbstractMultiEditor) part).getActiveEditor(); } // Real work. setActivePart(part, false); } /** * Resets the layout for the perspective. The active part in the old layout * is activated in the new layout for consistent user context. */ public void resetPerspective() { // Run op in busy cursor. // Use set redraw to eliminate the "flash" that can occur in the // coolbar as the perspective is reset. ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2(); try { mgr.getControl2().setRedraw(false); BusyIndicator.showWhile(null, new Runnable() { public void run() { busyResetPerspective(); } }); } finally { mgr.getControl2().setRedraw(true); } } /** * Restore this page from the memento and ensure that the active * perspective is equals the active descriptor otherwise create a new * perspective for that descriptor. If activeDescriptor is null active the * old perspective. */ public IStatus restoreState(IMemento memento, final IPerspectiveDescriptor activeDescriptor) { StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { deferUpdates(true); }}); try { // Restore working set String pageName = memento.getString(IWorkbenchConstants.TAG_LABEL); String label = null; // debugging only if (UIStats.isDebugging(UIStats.RESTORE_WORKBENCH)) { label = pageName == null ? "" : "::" + pageName; //$NON-NLS-1$ //$NON-NLS-2$ } try { UIStats.start(UIStats.RESTORE_WORKBENCH, "WorkbenchPage" + label); //$NON-NLS-1$ if (pageName == null) { pageName = ""; //$NON-NLS-1$ } final MultiStatus result = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, NLS.bind(WorkbenchMessages.get().WorkbenchPage_unableToRestorePerspective, pageName ), null); String workingSetName = memento .getString(IWorkbenchConstants.TAG_WORKING_SET); if (workingSetName != null) { AbstractWorkingSetManager workingSetManager = (AbstractWorkingSetManager) getWorkbenchWindow() .getWorkbench().getWorkingSetManager(); setWorkingSet(workingSetManager.getWorkingSet(workingSetName)); } IMemento workingSetMem = memento .getChild(IWorkbenchConstants.TAG_WORKING_SETS); if (workingSetMem != null) { IMemento[] workingSetChildren = workingSetMem .getChildren(IWorkbenchConstants.TAG_WORKING_SET); List workingSetList = new ArrayList( workingSetChildren.length); for (int i = 0; i < workingSetChildren.length; i++) { IWorkingSet set = getWorkbenchWindow().getWorkbench() .getWorkingSetManager().getWorkingSet( workingSetChildren[i].getID()); if (set != null) { workingSetList.add(set); } } workingSets = (IWorkingSet[]) workingSetList .toArray(new IWorkingSet[workingSetList.size()]); } aggregateWorkingSetId = memento.getString(ATT_AGGREGATE_WORKING_SET_ID); IWorkingSet setWithId = window.getWorkbench().getWorkingSetManager().getWorkingSet(aggregateWorkingSetId); // check to see if the set has already been made and assign it if it has if (setWithId instanceof AggregateWorkingSet) { aggregateWorkingSet = (AggregateWorkingSet) setWithId; } // Restore editor manager. IMemento childMem = memento .getChild(IWorkbenchConstants.TAG_EDITORS); result.merge(getEditorManager().restoreState(childMem)); childMem = memento.getChild(IWorkbenchConstants.TAG_VIEWS); if (childMem != null) { result.merge(getViewFactory().restoreState(childMem)); } // Get persp block. childMem = memento.getChild(IWorkbenchConstants.TAG_PERSPECTIVES); String activePartID = childMem .getString(IWorkbenchConstants.TAG_ACTIVE_PART); String activePartSecondaryID = null; if (activePartID != null) { activePartSecondaryID = ViewFactory .extractSecondaryId(activePartID); if (activePartSecondaryID != null) { activePartID = ViewFactory.extractPrimaryId(activePartID); } } final String activePerspectiveID = childMem .getString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE); // Restore perspectives. final IMemento perspMems[] = childMem .getChildren(IWorkbenchConstants.TAG_PERSPECTIVE); final Perspective activePerspectiveArray [] = new Perspective[1]; for (int i = 0; i < perspMems.length; i++) { final IMemento current = perspMems[i]; StartupThreading .runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { Perspective persp = ((WorkbenchImplementation) Tweaklets .get(WorkbenchImplementation.KEY)).createPerspective(null, WorkbenchPage.this); result.merge(persp.restoreState(current)); final IPerspectiveDescriptor desc = persp .getDesc(); if (desc.equals(activeDescriptor)) { activePerspectiveArray[0] = persp; } else if ((activePerspectiveArray[0] == null) && desc.getId().equals( activePerspectiveID)) { activePerspectiveArray[0] = persp; } perspList.add(persp); window.firePerspectiveOpened( WorkbenchPage.this, desc); } }); } Perspective activePerspective = activePerspectiveArray[0]; boolean restoreActivePerspective = false; if (activeDescriptor == null) { restoreActivePerspective = true; } else if (activePerspective != null && activePerspective.getDesc().equals(activeDescriptor)) { restoreActivePerspective = true; } else { restoreActivePerspective = false; activePerspective = createPerspective((PerspectiveDescriptor) activeDescriptor, true); if (activePerspective == null) { result .merge(new Status( IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, NLS.bind(WorkbenchMessages.get().Workbench_showPerspectiveError, activeDescriptor.getId() ), null)); } } perspList.setActive(activePerspective); // Make sure we have a valid perspective to work with, // otherwise return. activePerspective = perspList.getActive(); if (activePerspective == null) { activePerspective = perspList.getNextActive(); perspList.setActive(activePerspective); } if (activePerspective != null && restoreActivePerspective) { result.merge(activePerspective.restoreState()); } if (activePerspective != null) { final Perspective myPerspective = activePerspective; final String myActivePartId = activePartID, mySecondaryId = activePartSecondaryID; StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { window.firePerspectiveActivated(WorkbenchPage.this, myPerspective .getDesc()); // Restore active part. if (myActivePartId != null) { IViewReference ref = myPerspective.findView( myActivePartId, mySecondaryId); if (ref != null) { activationList.setActive(ref); } } }}); } childMem = memento .getChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY); if (childMem != null) { navigationHistory.restoreState(childMem); } else if (getActiveEditor() != null) { navigationHistory.markEditor(getActiveEditor()); } // restore sticky view state stickyViewMan.restore(memento); return result; } finally { String blame = activeDescriptor == null ? pageName : activeDescriptor.getId(); UIStats.end(UIStats.RESTORE_WORKBENCH, blame, "WorkbenchPage" + label); //$NON-NLS-1$ } } finally { StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { deferUpdates(false); } }); } } /** * See IWorkbenchPage */ public boolean saveAllEditors(boolean confirm) { return saveAllEditors(confirm, false); } /** * @param confirm * @param addNonPartSources true if saveables from non-part sources should be saved too * @return false if the user cancelled * */ public boolean saveAllEditors(boolean confirm, boolean addNonPartSources) { return getEditorManager().saveAll(confirm, false, addNonPartSources); } /* * Saves the workbench part. */ protected boolean savePart(ISaveablePart saveable, IWorkbenchPart part, boolean confirm) { // Do not certify part do allow editors inside a multipageeditor to // call this. return getEditorManager().savePart(saveable, part, confirm); } /** * Saves an editors in the workbench. If <code>confirm</code> is <code>true</code> * the user is prompted to confirm the command. * * @param confirm * if user confirmation should be sought * @return <code>true</code> if the command succeeded, or <code>false</code> * if the user cancels the command */ public boolean saveEditor(IEditorPart editor, boolean confirm) { return savePart(editor, editor, confirm); } /** * Saves the current perspective. */ public void savePerspective() { Perspective persp = getActivePerspective(); if (persp == null) { return; } // Always unzoom. if (isZoomed()) { zoomOut(); } persp.saveDesc(); } /** * Saves the perspective. */ public void savePerspectiveAs(IPerspectiveDescriptor newDesc) { Perspective persp = getActivePerspective(); if (persp == null) { return; } IPerspectiveDescriptor oldDesc = persp.getDesc(); // Always unzoom. if (isZoomed()) { zoomOut(); } persp.saveDescAs(newDesc); window.firePerspectiveSavedAs(this, oldDesc, newDesc); } /** * Save the state of the page. */ public IStatus saveState(IMemento memento) { // We must unzoom to get correct layout. if (isZoomed()) { zoomOut(); } // Close any open Fast View hideFastView(); MultiStatus result = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, NLS.bind(WorkbenchMessages.get().WorkbenchPage_unableToSavePerspective, getLabel()), null); // Save editor manager. IMemento childMem = memento .createChild(IWorkbenchConstants.TAG_EDITORS); result.merge(editorMgr.saveState(childMem)); childMem = memento.createChild(IWorkbenchConstants.TAG_VIEWS); result.merge(getViewFactory().saveState(childMem)); // Create persp block. childMem = memento.createChild(IWorkbenchConstants.TAG_PERSPECTIVES); if (getPerspective() != null) { childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE, getPerspective().getId()); } if (getActivePart() != null) { if (getActivePart() instanceof IViewPart) { IViewReference ref = (IViewReference) getReference(getActivePart()); if (ref != null) { childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART, ViewFactory.getKey(ref)); } } else { childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART, getActivePart().getSite().getId()); } } // Save each perspective in opened order Iterator itr = perspList.iterator(); while (itr.hasNext()) { Perspective persp = (Perspective) itr.next(); IMemento gChildMem = childMem .createChild(IWorkbenchConstants.TAG_PERSPECTIVE); result.merge(persp.saveState(gChildMem)); } // Save working set if set if (workingSet != null) { memento.putString(IWorkbenchConstants.TAG_WORKING_SET, workingSet .getName()); } IMemento workingSetMem = memento .createChild(IWorkbenchConstants.TAG_WORKING_SETS); for (int i = 0; i < workingSets.length; i++) { workingSetMem.createChild(IWorkbenchConstants.TAG_WORKING_SET, workingSets[i].getName()); } if (aggregateWorkingSetId != null) { memento.putString(ATT_AGGREGATE_WORKING_SET_ID, aggregateWorkingSetId); } navigationHistory.saveState(memento .createChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY)); // save the sticky activation state stickyViewMan.save(memento); return result; } private String getId(IWorkbenchPart part) { return getId(getReference(part)); } private String getId(IWorkbenchPartReference ref) { if (ref == null) { return "null"; //$NON-NLS-1$ } return ref.getId(); } /** * Sets the active part. */ private void setActivePart(IWorkbenchPart newPart, boolean force) { // Optimize it. if (!force && (getActivePart() == newPart)) { return; } if (partBeingActivated != null) { if (partBeingActivated.getPart(false) != newPart) { WorkbenchPlugin.log(new RuntimeException(NLS.bind( "WARNING: Prevented recursive attempt to activate part {0} while still in the middle of activating part {1}", //$NON-NLS-1$ getId(newPart), getId(partBeingActivated)))); } return; } //No need to change the history if the active editor is becoming the // active part String label = null; // debugging only if (UIStats.isDebugging(UIStats.ACTIVATE_PART)) { label = newPart != null ? newPart.getTitle() : "none"; //$NON-NLS-1$ } try { IWorkbenchPartReference partref = getReference(newPart); IWorkbenchPartReference realPartRef = null; if (newPart != null) { IWorkbenchPartSite site = newPart.getSite(); if (site instanceof PartSite) { realPartRef = ((PartSite) site).getPane() .getPartReference(); } } partBeingActivated = realPartRef; UIStats.start(UIStats.ACTIVATE_PART, label); // Notify perspective. It may deactivate fast view. Perspective persp = getActivePerspective(); if (persp != null) { persp.partActivated(newPart); } // Deactivate old part IWorkbenchPart oldPart = getActivePart(); if (oldPart != null) { deactivatePart(oldPart); } // Set active part. if (newPart != null) { activationList.setActive(newPart); if (newPart instanceof IEditorPart) { makeActiveEditor((IEditorReference)realPartRef); } } activatePart(newPart); actionSwitcher.updateActivePart(newPart); partList.setActivePart(partref); } finally { partBeingActivated = null; Object blame = newPart == null ? (Object)this : newPart; UIStats.end(UIStats.ACTIVATE_PART, blame, label); } } /** * See IWorkbenchPage. */ public void setEditorAreaVisible(boolean showEditorArea) { Perspective persp = getActivePerspective(); if (persp == null) { return; } if (showEditorArea == persp.isEditorAreaVisible()) { return; } // If parts change always update zoom. if (isZoomed()) { zoomOut(); } // Update editor area visibility. if (showEditorArea) { persp.showEditorArea(); window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_AREA_SHOW); } else { persp.hideEditorArea(); updateActivePart(); window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_AREA_HIDE); } } /** * Sets the layout of the page. Assumes the new perspective is not null. * Keeps the active part if possible. Updates the window menubar and * toolbar if necessary. */ private void setPerspective(Perspective newPersp) { // Don't do anything if already active layout Perspective oldPersp = getActivePerspective(); if (oldPersp == newPersp) { return; } window.largeUpdateStart(); try { if (oldPersp != null) { // fire the pre-deactivate window.firePerspectivePreDeactivate(this, oldPersp.getDesc()); } if (newPersp != null) { IStatus status = newPersp.restoreState(); if (status.getSeverity() != IStatus.OK) { String title = WorkbenchMessages.get().WorkbenchPage_problemRestoringTitle; String msg = WorkbenchMessages.get().WorkbenchPage_errorReadingState; ErrorDialog.openError(getWorkbenchWindow().getShell(), title, msg, status); } } // Deactivate the old layout if (oldPersp != null) { oldPersp.onDeactivate(); // Notify listeners of deactivation window.firePerspectiveDeactivated(this, oldPersp.getDesc()); } // Activate the new layout perspList.setActive(newPersp); if (newPersp != null) { newPersp.onActivate(); // Notify listeners of activation window.firePerspectiveActivated(this, newPersp.getDesc()); } updateVisibility(oldPersp, newPersp); // Update the window window.updateActionSets(); // Update sticky views stickyViewMan.update(oldPersp, newPersp); } finally { window.largeUpdateEnd(); if (newPersp == null) { return; } IPerspectiveDescriptor desc = newPersp.getDesc(); if (desc == null) { return; } if (dirtyPerspectives.remove(desc.getId())) { suggestReset(); } } } void perspectiveActionSetChanged(Perspective perspective, IActionSetDescriptor descriptor, int changeType) { if (perspective == getActivePerspective()) { actionSets.change(descriptor, changeType); } } /* * Update visibility state of all views. */ private void updateVisibility(Perspective oldPersp, Perspective newPersp) { // Flag all parts in the old perspective IWorkbenchPartReference[] oldRefs = new IWorkbenchPartReference[0]; if (oldPersp != null) { oldRefs = oldPersp.getViewReferences(); for (int i = 0; i < oldRefs.length; i++) { PartPane pane = ((WorkbenchPartReference) oldRefs[i]).getPane(); pane.setInLayout(false); } } PerspectiveHelper pres = null; // Make parts in the new perspective visible if (newPersp != null) { pres = newPersp.getPresentation(); IWorkbenchPartReference[] newRefs = newPersp.getViewReferences(); for (int i = 0; i < newRefs.length; i++) { WorkbenchPartReference ref = (WorkbenchPartReference)newRefs[i]; PartPane pane = ref.getPane(); if (pres.isPartVisible(ref)) { activationList.bringToTop(ref); } pane.setInLayout(true); } } updateActivePart(); // Hide any parts in the old perspective that are no longer visible for (int i = 0; i < oldRefs.length; i++) { WorkbenchPartReference ref = (WorkbenchPartReference)oldRefs[i]; PartPane pane = ref.getPane(); if (pres == null || !pres.isPartVisible(ref)) { pane.setVisible(false); } } } /** * Sets the perspective. * * @param desc * identifies the new perspective. */ public void setPerspective(final IPerspectiveDescriptor desc) { if (Util.equals(getPerspective(), desc)) { return; } // Going from multiple to single rows can make the coolbar // and its adjacent views appear jumpy as perspectives are // switched. Turn off redraw to help with this. ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2(); try { if (mgr != null) mgr.getControl2().setRedraw(false); getClientComposite().setRedraw(false); // Run op in busy cursor. BusyIndicator.showWhile(null, new Runnable() { public void run() { busySetPerspective(desc); } }); } finally { getClientComposite().setRedraw(true); if (mgr != null) mgr.getControl2().setRedraw(true); IWorkbenchPart part = getActivePart(); if (part != null) { part.setFocus(); } } } /** * Allow access to the part service for this page ... used internally to * propogate certain types of events to the page part listeners. * @return the part service for this page. */ public PartService getPartService() { return (PartService)partList.getPartService(); } /** * Restore the toolbar layout for the active perspective. */ protected void resetToolBarLayout() { ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2(); mgr.resetItemOrder(); } /** * Sets the active working set for the workbench page. Notifies property * change listener about the change. * * @param newWorkingSet * the active working set for the page. May be null. * @deprecated individual views should store a working set if needed */ public void setWorkingSet(IWorkingSet newWorkingSet) { IWorkingSet oldWorkingSet = workingSet; workingSet = newWorkingSet; if (oldWorkingSet != newWorkingSet) { firePropertyChange(CHANGE_WORKING_SET_REPLACE, oldWorkingSet, newWorkingSet); } if (newWorkingSet != null) { WorkbenchPlugin.getDefault().getWorkingSetManager() .addPropertyChangeListener(workingSetPropertyChangeListener); } else { WorkbenchPlugin.getDefault().getWorkingSetManager() .removePropertyChangeListener(workingSetPropertyChangeListener); } } /** * @see IWorkbenchPage */ public void showActionSet(String actionSetID) { Perspective persp = getActivePerspective(); if (persp != null) { ActionSetRegistry reg = WorkbenchPlugin.getDefault() .getActionSetRegistry(); IActionSetDescriptor desc = reg.findActionSet(actionSetID); if (desc != null) { persp.addActionSet(desc); window.updateActionSets(); window.firePerspectiveChanged(this, getPerspective(), CHANGE_ACTION_SET_SHOW); } } } /** * See IWorkbenchPage. */ public IViewPart showView(String viewID) throws PartInitException { return showView(viewID, null, VIEW_ACTIVATE); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String, * java.lang.String, int) */ public IViewPart showView(final String viewID, final String secondaryID, final int mode) throws PartInitException { if (secondaryID != null) { if (secondaryID.length() == 0 || secondaryID.indexOf(ViewFactory.ID_SEP) != -1) { throw new IllegalArgumentException(WorkbenchMessages.get().WorkbenchPage_IllegalSecondaryId); } } if (!certifyMode(mode)) { throw new IllegalArgumentException(WorkbenchMessages.get().WorkbenchPage_IllegalViewMode); } // Run op in busy cursor. final Object[] result = new Object[1]; BusyIndicator.showWhile(null, new Runnable() { public void run() { try { result[0] = busyShowView(viewID, secondaryID, mode); } catch (PartInitException e) { result[0] = e; } } }); if (result[0] instanceof IViewPart) { return (IViewPart) result[0]; } else if (result[0] instanceof PartInitException) { throw (PartInitException) result[0]; } else { throw new PartInitException(WorkbenchMessages.get().WorkbenchPage_AbnormalWorkbenchCondition); } } /** * @param mode the mode to test * @return whether the mode is recognized */ private boolean certifyMode(int mode) { switch (mode) { case VIEW_ACTIVATE: case VIEW_VISIBLE: case VIEW_CREATE: return true; default: return false; } } /** * Hides the active fast view. Has no effect if there is no fast view active. */ public void hideFastView() { Perspective persp = getActivePerspective(); if (persp != null) { IViewReference ref = persp.getActiveFastView(); if (ref != null) { toggleFastView(ref); } } } /** * Toggles the visibility of a fast view. If the view is active it is * deactivated. Otherwise, it is activated. */ public void toggleFastView(IViewReference ref) { Perspective persp = getActivePerspective(); if (persp != null) { persp.toggleFastView(ref); // if the fast view has been deactivated if (ref != persp.getActiveFastView()) { IWorkbenchPart previouslyActive = activationList .getPreviouslyActive(); IEditorPart activeEditor = getActiveEditor(); if (activeEditor != null && previouslyActive instanceof IEditorPart) { setActivePart(activeEditor, false); } else { setActivePart(previouslyActive, false); } } } } /** * Sets the state of the given part. * * @param ref part whose state should be modified (not null) * @param newState one of the IStackPresentationSite.STATE_* constants */ public void setState(IWorkbenchPartReference ref, int newState) { Perspective persp = getActivePerspective(); if (persp == null) { return; } PartPane pane = ((WorkbenchPartReference) ref).getPane(); // If target part is detached fire the zoom event. Note this doesn't // actually cause any changes in size and is required to support // intro state changes. We may want to introduce the notion of a zoomed // (fullscreen) detached view at a later time. if (!pane.isDocked()) { pane.setZoomed(newState == IStackPresentationSite.STATE_MAXIMIZED); return; } if (ref instanceof IViewReference && persp.isFastView((IViewReference) ref)) { persp.setFastViewState((IViewReference) ref, newState); return; } if (Perspective.useNewMinMax(persp)) { // set the container's state to the new one PartStack parent = ((PartStack)pane.getContainer()); parent.setState(newState); return; } boolean wasZoomed = isZoomed(); boolean isZoomed = newState == IStackPresentationSite.STATE_MAXIMIZED; // Update zoom status. if (wasZoomed && !isZoomed) { zoomOut(); } else if (!wasZoomed && isZoomed) { persp.getPresentation().zoomIn(ref); activate(ref.getPart(true)); } PartStack parent = ((PartStack)pane.getContainer()); if (parent != null) { parent.setMinimized(newState == IStackPresentationSite.STATE_MINIMIZED); } } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPage#setPartState(org.eclipse.ui.IWorkbenchPartReference, int) */ public void setPartState(IWorkbenchPartReference ref, int state) { setState(ref, state); } /** * Returns the maximized/minimized/restored state of the given part reference * * @param ref part to query (not null) * @return one of the IStackPresentationSite.STATE_* constants */ int getState(IWorkbenchPartReference ref) { Perspective persp = getActivePerspective(); if (persp == null) { return IStackPresentationSite.STATE_RESTORED; } PartPane pane = ((WorkbenchPartReference) ref).getPane(); if (ref instanceof IViewReference && persp.isFastView((IViewReference) ref)) { return persp.getFastViewState(); } PartStack parent = ((PartStack)pane.getContainer()); if (parent != null) { return parent.getState(); } return IStackPresentationSite.STATE_RESTORED; } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPage#getPartState(org.eclipse.ui.IWorkbenchPartReference) */ public int getPartState(IWorkbenchPartReference ref) { return getState(ref); } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPage#toggleZoom(org.eclipse.ui.IWorkbenchPartReference) */ public void toggleZoom(IWorkbenchPartReference ref) { int oldState = getState(ref); boolean shouldZoom = oldState != IStackPresentationSite.STATE_MAXIMIZED; int newState = shouldZoom ? IStackPresentationSite.STATE_MAXIMIZED : IStackPresentationSite.STATE_RESTORED; setState(ref, newState); } /** * updateActionBars method comment. */ public void updateActionBars() { window.updateActionBars(); } /** * Sets the tab list of this page's composite appropriately when a part is * activated. */ private void updateTabList(IWorkbenchPart part) { PartSite site = (PartSite) part.getSite(); PartPane pane = site.getPane(); if (pane instanceof ViewPane) { ViewPane viewPane = (ViewPane) pane; Control[] tabList = viewPane.getTabList(); if (!pane.isDocked()) { viewPane.getControl().getShell().setTabList(tabList); } else { getClientComposite().setTabList(tabList); } } else if (pane instanceof EditorPane) { EditorSashContainer ea = ((EditorPane) pane).getWorkbook() .getEditorArea(); ea.updateTabList(); getClientComposite().setTabList(new Control[] { ea.getParent() }); } } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPage#zoomOut() */ public void zoomOut() { Perspective persp = getActivePerspective(); if (persp != null) { persp.getPresentation().zoomOut(); } } /** * Zooms out a zoomed in part if it is necessary to do so for the user to * view the IWorkbenchPart that is the argument. Otherwise, does nothing. * * @param part * the part to be made viewable */ private void zoomOutIfNecessary(IWorkbenchPart part) { if (isZoomed() && partChangeAffectsZoom(((PartSite)part.getSite()).getPartReference())) { zoomOut(); } } /** * */ public int getEditorReuseThreshold() { return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getEditorReuseThreshold(); } /** * */ public void setEditorReuseThreshold(int openEditors) { } /* * Returns the editors in activation order (oldest first). */ public IEditorReference[] getSortedEditors() { return activationList.getEditors(); } /** * @see IWorkbenchPage#getOpenPerspectives() */ public IPerspectiveDescriptor[] getOpenPerspectives() { Perspective opened[] = perspList.getOpenedPerspectives(); IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[opened.length]; for (int i = 0; i < result.length; i++) { result[i] = opened[i].getDesc(); } return result; } /** * Return all open Perspective objects. * * @return all open Perspective objects */ /*package*/Perspective [] getOpenInternalPerspectives() { return perspList.getOpenedPerspectives(); } /** * Checks perspectives in the order they were activiated * for the specfied part. The first sorted perspective * that contains the specified part is returned. * * @param part specified part to search for * @return the first sorted perspespective containing the part */ /*package*/Perspective getFirstPerspectiveWithView(IViewPart part) { Perspective [] perspectives = perspList.getSortedPerspectives(); for (int i=perspectives.length - 1; i >= 0; i--) { if (perspectives[i].containsView(part)) { return perspectives[i]; } } // we should never get here return null; } /** * Returns the perspectives in activation order (oldest first). */ public IPerspectiveDescriptor[] getSortedPerspectives() { Perspective sortedArray[] = perspList.getSortedPerspectives(); IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[sortedArray.length]; for (int i = 0; i < result.length; i++) { result[i] = sortedArray[i].getDesc(); } return result; } /* * Returns the parts in activation order (oldest first). */ public IWorkbenchPartReference[] getSortedParts() { return activationList.getParts(); } /** * Returns the reference to the given part, or <code>null</code> if it has no reference * (i.e. it is not a top-level part in this workbench page). * * @param part the part * @return the part's reference or <code>null</code> if the given part does not belong * to this workbench page */ public IWorkbenchPartReference getReference(IWorkbenchPart part) { if (part == null) { return null; } IWorkbenchPartSite site = part.getSite(); if (!(site instanceof PartSite)) { return null; } PartSite partSite = ((PartSite) site); PartPane pane = partSite.getPane(); if (pane instanceof MultiEditorInnerPane) { MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane; return innerPane.getParentPane().getPartReference(); } return partSite.getPartReference(); } private class ActivationList { //List of parts in the activation order (oldest first) List parts = new ArrayList(); /* * Add/Move the active part to end of the list; */ void setActive(IWorkbenchPart part) { if (parts.size() <= 0) { return; } IWorkbenchPartReference ref = getReference(part); if (ref != null) { if (ref == parts.get(parts.size() - 1)) { return; } parts.remove(ref); parts.add(ref); } } /* * Ensures that the given part appears AFTER any other part in the same * container. */ void bringToTop(IWorkbenchPartReference ref) { ILayoutContainer targetContainer = getContainer(ref); int newIndex = lastIndexOfContainer(targetContainer); //New index can be -1 if there is no last index if (newIndex >= 0 && ref == parts.get(newIndex)) return; parts.remove(ref); if(newIndex >= 0) parts.add(newIndex, ref); else parts.add(ref); } /* * Returns the last (most recent) index of the given container in the activation list, or returns * -1 if the given container does not appear in the activation list. */ int lastIndexOfContainer(ILayoutContainer container) { for (int i = parts.size() - 1; i >= 0; i--) { IWorkbenchPartReference ref = (IWorkbenchPartReference)parts.get(i); ILayoutContainer cnt = getContainer(ref); if (cnt == container) { return i; } } return -1; } /* * Add/Move the active part to end of the list; */ void setActive(IWorkbenchPartReference ref) { setActive(ref.getPart(true)); } /* * Add the active part to the beginning of the list. */ void add(IWorkbenchPartReference ref) { if (parts.indexOf(ref) >= 0) { return; } IWorkbenchPart part = ref.getPart(false); if (part != null) { PartPane pane = ((PartSite) part.getSite()).getPane(); if (pane instanceof MultiEditorInnerPane) { MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane; add(innerPane.getParentPane().getPartReference()); return; } } parts.add(0, ref); } /* * Return the previously active part. Filter fast views. */ IWorkbenchPart getPreviouslyActive() { if (parts.size() < 2) { return null; } return getActive(parts.size() - 2); } private IWorkbenchPart getActive(int start) { IWorkbenchPartReference ref = getActiveReference(start, false); if (ref == null) { return null; } return ref.getPart(true); } public IWorkbenchPartReference getActiveReference(boolean editorsOnly) { return getActiveReference(parts.size() - 1, editorsOnly); } private IWorkbenchPartReference getActiveReference(int start, boolean editorsOnly) { // First look for parts that aren't obscured by the current zoom state IWorkbenchPartReference nonObscured = getActiveReference(start, editorsOnly, true); if (nonObscured != null) { return nonObscured; } // Now try all the rest of the parts return getActiveReference(start, editorsOnly, false); } /* * Find a part in the list starting from the end and filter * and views from other perspectives. Will filter fast views * unless 'includeActiveFastViews' is true; */ private IWorkbenchPartReference getActiveReference(int start, boolean editorsOnly, boolean skipPartsObscuredByZoom) { IWorkbenchPartReference[] views = getViewReferences(); for (int i = start; i >= 0; i--) { WorkbenchPartReference ref = (WorkbenchPartReference) parts .get(i); if (editorsOnly && !(ref instanceof IEditorReference)) { continue; } // Skip parts whose containers have disabled auto-focus PartPane pane = ref.getPane(); if (pane != null) { if (!pane.allowsAutoFocus()) { continue; } if (skipPartsObscuredByZoom) { if (pane.isObscuredByZoom()) { continue; } } } // Skip fastviews (unless overridden) if (ref instanceof IViewReference) { if (ref == getActiveFastView() || !((IViewReference) ref).isFastView()) { for (int j = 0; j < views.length; j++) { if (views[j] == ref) { return ref; } } } } else { return ref; } } return null; } /* * Returns the index of the part reference within the activation list. * The higher the index, the more recent it was used. */ int indexOf(IWorkbenchPartReference ref) { return parts.indexOf(ref); } /* * Remove a part from the list */ boolean remove(IWorkbenchPartReference ref) { return parts.remove(ref); } /* * Returns the editors in activation order (oldest first). */ private IEditorReference[] getEditors() { ArrayList editors = new ArrayList(parts.size()); for (Iterator i = parts.iterator(); i.hasNext();) { IWorkbenchPartReference part = (IWorkbenchPartReference) i .next(); if (part instanceof IEditorReference) { editors.add(part); } } return (IEditorReference[]) editors .toArray(new IEditorReference[editors.size()]); } /* * Return a list with all parts (editors and views). */ private IWorkbenchPartReference[] getParts() { IWorkbenchPartReference[] views = getViewReferences(); ArrayList resultList = new ArrayList(parts.size()); for (Iterator iterator = parts.iterator(); iterator.hasNext();) { IWorkbenchPartReference ref = (IWorkbenchPartReference) iterator .next(); if (ref instanceof IViewReference) { //Filter views from other perspectives for (int i = 0; i < views.length; i++) { if (views[i] == ref) { resultList.add(ref); break; } } } else { resultList.add(ref); } } IWorkbenchPartReference[] result = new IWorkbenchPartReference[resultList .size()]; return (IWorkbenchPartReference[]) resultList.toArray(result); } } /** * Helper class to keep track of all opened perspective. Both the opened * and used order is kept. */ private class PerspectiveList { /** * List of perspectives in the order they were opened; */ private List openedList; /** * List of perspectives in the order they were used. Last element is * the most recently used, and first element is the least recently * used. */ private List usedList; /** * The perspective explicitly set as being the active one */ private Perspective active; /** * Creates an empty instance of the perspective list */ public PerspectiveList() { openedList = new ArrayList(); usedList = new ArrayList(); } /** * Update the order of the perspectives in the opened list * * @param perspective * @param newLoc */ public void reorder(IPerspectiveDescriptor perspective, int newLoc) { int oldLocation = 0; Perspective movedPerspective = null; for (Iterator iterator = openedList.iterator(); iterator.hasNext();) { Perspective openPerspective = (Perspective) iterator.next(); if (openPerspective.getDesc().equals(perspective)) { oldLocation = openedList.indexOf(openPerspective); movedPerspective = openPerspective; } } if (oldLocation == newLoc) { return; } openedList.remove(oldLocation); openedList.add(newLoc, movedPerspective); } /** * Return all perspectives in the order they were activated. * * @return an array of perspectives sorted by activation order, least * recently activated perspective last. */ public Perspective[] getSortedPerspectives() { Perspective[] result = new Perspective[usedList.size()]; return (Perspective[]) usedList.toArray(result); } /** * Adds a perspective to the list. No check is done for a duplicate when * adding. * @param perspective the perspective to add * @return boolean <code>true</code> if the perspective was added */ public boolean add(Perspective perspective) { openedList.add(perspective); usedList.add(0, perspective); //It will be moved to top only when activated. return true; } /** * Returns an iterator on the perspective list in the order they were * opened. */ public Iterator iterator() { return openedList.iterator(); } /** * Returns an array with all opened perspectives */ public Perspective[] getOpenedPerspectives() { Perspective[] result = new Perspective[openedList.size()]; return (Perspective[]) openedList.toArray(result); } /** * Removes a perspective from the list. */ public boolean remove(Perspective perspective) { if (active == perspective) { updateActionSets(active, null); active = null; } usedList.remove(perspective); return openedList.remove(perspective); } /** * Swap the opened order of old perspective with the new perspective. */ public void swap(Perspective oldPerspective, Perspective newPerspective) { int oldIndex = openedList.indexOf(oldPerspective); int newIndex = openedList.indexOf(newPerspective); if (oldIndex < 0 || newIndex < 0) { return; } openedList.set(oldIndex, newPerspective); openedList.set(newIndex, oldPerspective); } /** * Returns whether the list contains any perspectives */ public boolean isEmpty() { return openedList.isEmpty(); } /** * Returns the most recently used perspective in the list. */ public Perspective getActive() { return active; } /** * Returns the next most recently used perspective in the list. */ public Perspective getNextActive() { if (active == null) { if (usedList.isEmpty()) { return null; } else { return (Perspective) usedList.get(usedList.size() - 1); } } else { if (usedList.size() < 2) { return null; } else { return (Perspective) usedList.get(usedList.size() - 2); } } } /** * Returns the number of perspectives opened */ public int size() { return openedList.size(); } /** * Marks the specified perspective as the most recently used one in the * list. */ public void setActive(Perspective perspective) { if (perspective == active) { return; } updateActionSets(active, perspective); active = perspective; if (perspective != null) { usedList.remove(perspective); usedList.add(perspective); } } private void updateActionSets(Perspective oldPersp, Perspective newPersp) { // Update action sets IContextService service = (IContextService) window .getService(IContextService.class); try { service.deferUpdates(true); if (newPersp != null) { IActionSetDescriptor[] newAlwaysOn = newPersp .getAlwaysOnActionSets(); for (int i = 0; i < newAlwaysOn.length; i++) { IActionSetDescriptor descriptor = newAlwaysOn[i]; actionSets.showAction(descriptor); } IActionSetDescriptor[] newAlwaysOff = newPersp .getAlwaysOffActionSets(); for (int i = 0; i < newAlwaysOff.length; i++) { IActionSetDescriptor descriptor = newAlwaysOff[i]; actionSets.maskAction(descriptor); } } if (oldPersp != null) { IActionSetDescriptor[] newAlwaysOn = oldPersp .getAlwaysOnActionSets(); for (int i = 0; i < newAlwaysOn.length; i++) { IActionSetDescriptor descriptor = newAlwaysOn[i]; actionSets.hideAction(descriptor); } IActionSetDescriptor[] newAlwaysOff = oldPersp .getAlwaysOffActionSets(); for (int i = 0; i < newAlwaysOff.length; i++) { IActionSetDescriptor descriptor = newAlwaysOff[i]; actionSets.unmaskAction(descriptor); } } } finally { service.deferUpdates(false); } } } // for dynamic UI protected void addPerspective(Perspective persp) { perspList.add(persp); window.firePerspectiveOpened(this, persp.getDesc()); } /** * Find the stack of view references stacked with this view part. * * @param part * the part * @return the stack of references */ private IViewReference[] getViewReferenceStack(IViewPart part) { // Sanity check. Perspective persp = getActivePerspective(); if (persp == null || !certifyPart(part)) { return null; } ILayoutContainer container = ((PartSite) part.getSite()).getPane() .getContainer(); if (container instanceof ViewStack) { ViewStack folder = (ViewStack) container; final ArrayList list = new ArrayList(folder.getChildren().length); for (int i = 0; i < folder.getChildren().length; i++) { LayoutPart layoutPart = folder.getChildren()[i]; if (layoutPart instanceof ViewPane) { IViewReference view = ((ViewPane) layoutPart) .getViewReference(); if (view != null) { list.add(view); } } } // sort the list by activation order (most recently activated first) Collections.sort(list, new Comparator() { public int compare(Object o1, Object o2) { int pos1 = (-1) * activationList .indexOf((IWorkbenchPartReference) o1); int pos2 = (-1) * activationList .indexOf((IWorkbenchPartReference) o2); return pos1 - pos2; } }); return (IViewReference[]) list.toArray(new IViewReference[list .size()]); } return new IViewReference[] { (IViewReference) getReference(part) }; } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage#getViewStack(org.eclipse.ui.IViewPart) */ public IViewPart[] getViewStack(IViewPart part) { IViewReference[] refStack = getViewReferenceStack(part); if (refStack == null) { return null; } List result = new ArrayList(); for (int i = 0; i < refStack.length; i++) { IViewPart next = refStack[i].getView(false); if (next != null) { result.add(next); } } return (IViewPart[]) result.toArray(new IViewPart[result.size()]); } /** * Allow for programmatically resizing a part. * <p> * <em>EXPERIMENTAL</em> * </p> * <p> * Known limitations: * <ul> * <li>currently applies only to views</li> * <li>has no effect when view is zoomed</li> * </ul> * <p> * <b>Note:</b> At the time of the writing of this note, this method does * not appear to be used anywhere in the workbench. Please refer to bug * 126622. * </p> */ public void resizeView(IViewPart part, int width, int height) { SashInfo sashInfo = new SashInfo(); PartPane pane = ((PartSite) part.getSite()).getPane(); ILayoutContainer container = pane.getContainer(); LayoutTree tree = getPerspectivePresentation().getLayout().root .find(((ViewStack) container)); // retrieve our layout sashes from the layout tree findSashParts(tree, pane.findSashes(), sashInfo); // first set the width float deltaWidth = width - pane.getBounds().width; if (sashInfo.right != null) { Rectangle rightBounds = sashInfo.rightNode.getBounds(); // set the new ratio sashInfo.right.setRatio(((deltaWidth + sashInfo.right .getBounds().x) - rightBounds.x) / rightBounds.width); // complete the resize sashInfo.rightNode.setBounds(rightBounds); } else if (sashInfo.left != null) { Rectangle leftBounds = sashInfo.leftNode.getBounds(); // set the ratio sashInfo.left .setRatio(((sashInfo.left.getBounds().x - deltaWidth) - leftBounds.x) / leftBounds.width); // complete the resize sashInfo.leftNode.setBounds(sashInfo.leftNode.getBounds()); } // next set the height float deltaHeight = height - pane.getBounds().height; if (sashInfo.bottom != null) { Rectangle bottomBounds = sashInfo.bottomNode.getBounds(); // set the new ratio sashInfo.bottom.setRatio(((deltaHeight + sashInfo.bottom .getBounds().y) - bottomBounds.y) / bottomBounds.height); // complete the resize sashInfo.bottomNode.setBounds(bottomBounds); } else if (sashInfo.top != null) { Rectangle topBounds = sashInfo.topNode.getBounds(); // set the ratio sashInfo.top .setRatio(((sashInfo.top.getBounds().y - deltaHeight) - topBounds.y) / topBounds.height); // complete the resize sashInfo.topNode.setBounds(topBounds); } } // provides sash information for the given pane private class SashInfo { private LayoutPartSash right; private LayoutPartSash left; private LayoutPartSash top; private LayoutPartSash bottom; private LayoutTreeNode rightNode; private LayoutTreeNode leftNode; private LayoutTreeNode topNode; private LayoutTreeNode bottomNode; } private void findSashParts(LayoutTree tree, PartPane.Sashes sashes, SashInfo info) { LayoutTree parent = tree.getParent(); if (parent == null) { return; } if (parent.part instanceof LayoutPartSash) { // get the layout part sash from this tree node LayoutPartSash sash = (LayoutPartSash) parent.part; // make sure it has a sash control Control control = sash.getControl(); if (control != null) { // check for a vertical sash if (sash.isVertical()) { if (sashes.left == control) { info.left = sash; info.leftNode = parent.findSash(sash); } else if (sashes.right == control) { info.right = sash; info.rightNode = parent.findSash(sash); } } // check for a horizontal sash else { if (sashes.top == control) { info.top = sash; info.topNode = parent.findSash(sash); } else if (sashes.bottom == control) { info.bottom = sash; info.bottomNode = parent.findSash(sash); } } } } // recursive call to continue up the tree findSashParts(parent, sashes, info); } /** * Returns all parts that are owned by this page * * @return all open parts, including non-participating editors. */ IWorkbenchPartReference[] getAllParts() { ArrayList allParts = new ArrayList(); IViewReference[] views = viewFactory.getViews(); IEditorReference[] editors = getEditorReferences(); if (views.length > 0) { allParts.addAll(Arrays.asList(views)); } if (editors.length > 0) { allParts.addAll(Arrays.asList(editors)); } if (removedEditors.size() > 0) { allParts.addAll(removedEditors); } return (IWorkbenchPartReference[]) allParts .toArray(new IWorkbenchPartReference[allParts.size()]); } /** * Returns all open parts that are owned by this page (that is, all parts * for which a part opened event would have been sent -- these would be * activated parts whose controls have already been created. */ IWorkbenchPartReference[] getOpenParts() { IWorkbenchPartReference[] refs = getAllParts(); List result = new ArrayList(); for (int i = 0; i < refs.length; i++) { IWorkbenchPartReference reference = refs[i]; IWorkbenchPart part = reference.getPart(false); if (part != null) { result.add(reference); } } return (IWorkbenchPartReference[]) result.toArray(new IWorkbenchPartReference[result.size()]); } /** * Sanity-checks the objects in this page. Throws an Assertation exception * if an object's internal state is invalid. ONLY INTENDED FOR USE IN THE * UI TEST SUITES. */ public void testInvariants() { Perspective persp = getActivePerspective(); if (persp != null) { persp.testInvariants(); // When we have widgets, ensure that there is no situation where the editor area is visible // and the perspective doesn't want an editor area. if (!SwtUtil.isDisposed(getClientComposite()) && editorPresentation.getLayoutPart().isVisible()) { Assert.isTrue(persp.isEditorAreaVisible()); } } } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPage#getExtensionTracker() */ public IExtensionTracker getExtensionTracker() { if (tracker == null) { tracker = new UIExtensionTracker(getWorkbenchWindow().getWorkbench().getDisplay()); } return tracker; } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage#getNewWizardShortcuts() */ public String[] getNewWizardShortcuts() { Perspective persp = getActivePerspective(); if (persp == null) { return new String[0]; } return persp.getNewWizardShortcuts(); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage#getPerspectiveShortcuts() */ public String[] getPerspectiveShortcuts() { Perspective persp = getActivePerspective(); if (persp == null) { return new String[0]; } return persp.getPerspectiveShortcuts(); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPage#getShowViewShortcuts() */ public String[] getShowViewShortcuts() { Perspective persp = getActivePerspective(); if (persp == null) { return new String[0]; } return persp.getShowViewShortcuts(); } /** */ private void suggestReset() { final IWorkbench workbench = getWorkbenchWindow().getWorkbench(); workbench.getDisplay().asyncExec(new Runnable() { public void run() { Shell parentShell = null; IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); if (window == null) { if (workbench.getWorkbenchWindowCount() == 0) { return; } window = workbench.getWorkbenchWindows()[0]; } parentShell = window.getShell(); if (MessageDialog .openQuestion( parentShell, WorkbenchMessages.get().Dynamic_resetPerspectiveTitle, WorkbenchMessages.get().Dynamic_resetPerspectiveMessage)) { IWorkbenchPage page = window.getActivePage(); if (page == null) { return; } page.resetPerspective(); } } }); } public boolean isPartVisible(IWorkbenchPartReference reference) { IWorkbenchPart part = reference.getPart(false); // Can't be visible if it isn't created yet if (part == null) { return false; } return isPartVisible(part); } public IWorkingSet[] getWorkingSets() { return workingSets; } public void setWorkingSets(IWorkingSet[] newWorkingSets) { if (newWorkingSets != null) { WorkbenchPlugin .getDefault() .getWorkingSetManager() .addPropertyChangeListener(workingSetPropertyChangeListener); } else { WorkbenchPlugin.getDefault().getWorkingSetManager() .removePropertyChangeListener( workingSetPropertyChangeListener); } if (newWorkingSets == null) { newWorkingSets = new IWorkingSet[0]; } IWorkingSet[] oldWorkingSets = workingSets; // filter out any duplicates if necessary if (newWorkingSets.length > 1) { Set setOfSets = new HashSet(); for (int i = 0; i < newWorkingSets.length; i++) { if (newWorkingSets[i] == null) { throw new IllegalArgumentException(); } setOfSets.add(newWorkingSets[i]); } newWorkingSets = (IWorkingSet[]) setOfSets .toArray(new IWorkingSet[setOfSets.size()]); } workingSets = newWorkingSets; if (!Arrays.equals(oldWorkingSets, newWorkingSets)) { firePropertyChange(CHANGE_WORKING_SETS_REPLACE, oldWorkingSets, newWorkingSets); if (aggregateWorkingSet != null) { aggregateWorkingSet.setComponents(workingSets); } } } public IWorkingSet getAggregateWorkingSet() { if (aggregateWorkingSet == null) { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() .getWorkingSetManager(); aggregateWorkingSet = (AggregateWorkingSet) workingSetManager.getWorkingSet( getAggregateWorkingSetId()); if (aggregateWorkingSet == null) { aggregateWorkingSet = (AggregateWorkingSet) workingSetManager .createAggregateWorkingSet( getAggregateWorkingSetId(), WorkbenchMessages.get().WorkbenchPage_workingSet_default_label, getWorkingSets()); workingSetManager.addWorkingSet(aggregateWorkingSet); } } return aggregateWorkingSet; } private String getAggregateWorkingSetId() { if (aggregateWorkingSetId == null) { aggregateWorkingSetId = "Aggregate for window " + System.currentTimeMillis(); //$NON-NLS-1$ } return aggregateWorkingSetId; } public void showEditor(IEditorReference ref) { if (((WorkbenchPartReference)ref).isDisposed()) { WorkbenchPlugin.log("adding a disposed part: " + ref); //$NON-NLS-1$ return; } if (editorPresentation.containsEditor((EditorReference) ref)) { return; } removedEditors.remove(ref); editorPresentation.addEditor((EditorReference) ref, "", false); //$NON-NLS-1$ activationList.add(ref); updateActivePart(); } public void hideEditor(IEditorReference ref) { if (!editorPresentation.containsEditor((EditorReference) ref)) { return; } editorPresentation.closeEditor(ref); activationList.remove(ref); // all editors need a place to go so they can have a coffee and a doughnut removedEditors.add(ref); updateActivePart(); // partList.removePart((WorkbenchPartReference)ref); } public IEditorReference[] openEditors(final IEditorInput[] inputs, final String[] editorIDs, final int matchFlags) throws MultiPartInitException { if (inputs == null) throw new IllegalArgumentException(); if (editorIDs == null) throw new IllegalArgumentException(); if (inputs.length != editorIDs.length) throw new IllegalArgumentException(); final IEditorReference[] results = new IEditorReference[inputs.length]; final PartInitException[] exceptions = new PartInitException[inputs.length]; BusyIndicator.showWhile(window.getWorkbench().getDisplay(), new Runnable() { public void run() { Workbench workbench = (Workbench) getWorkbenchWindow().getWorkbench(); workbench.largeUpdateStart(); try { deferUpdates(true); for (int i = inputs.length - 1; i >= 0; i--) { if (inputs[i] == null || editorIDs[i] == null) throw new IllegalArgumentException(); // activate the first editor boolean activate = (i == 0); try { // check if there is an editor we can reuse IEditorReference ref = batchReuseEditor(inputs[i], editorIDs[i], activate, matchFlags); if (ref == null) // otherwise, create a new one ref = batchOpenEditor(inputs[i], editorIDs[i], activate); results[i] = ref; } catch (PartInitException e) { exceptions[i] = e; results[i] = null; } } deferUpdates(false); // Update activation history. This can't be done // "as we go" or editors will be materialized. for (int i = inputs.length - 1; i >= 0; i--) { if (results[i] == null) continue; activationList.bringToTop(results[i]); } // The first request for activation done above is // required to properly position editor tabs. // However, when it is done the updates are deferred // and container of the editor is not visible. // As a result the focus is not set. // Therefore, find the first created editor and // activate it again: for (int i = 0; i < results.length; i++) { if (results[i] == null) continue; IEditorPart editorPart = results[i] .getEditor(true); if (editorPart == null) continue; if (editorPart instanceof AbstractMultiEditor) internalActivate( ((AbstractMultiEditor) editorPart) .getActiveEditor(), true); else internalActivate(editorPart, true); break; } } finally { workbench.largeUpdateEnd(); } } }); boolean hasException = false; for(int i = 0 ; i < results.length; i++) { if (exceptions[i] != null) { hasException = true; } if (results[i] == null) { continue; } window.firePerspectiveChanged(this, getPerspective(), results[i], CHANGE_EDITOR_OPEN); } window.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); if (hasException) { throw new MultiPartInitException(results, exceptions); } return results; } private IEditorReference batchReuseEditor(IEditorInput input, String editorID, boolean activate, int matchFlags) { if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID.equals( editorID)) return null; // don't reuse external editors int flag = ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getReuseEditorMatchFlags(matchFlags); IEditorReference[] refs = getEditorManager().findEditors(input, editorID, flag); if (refs.length == 0) return null; IEditorPart editor = refs[0].getEditor(activate); if (editor != null && activate) { // do the IShowEditorInput notification before showing the editor to reduce flicker if (editor instanceof IShowEditorInput) ((IShowEditorInput) editor).showEditorInput(input); showEditor(activate, editor); } return refs[0]; } private IEditorReference batchOpenEditor(IEditorInput input, String editorID, boolean activate) throws PartInitException { IEditorPart editor = null; IEditorReference ref; try { partBeingOpened = true; ref = getEditorManager().openEditor(editorID, input, true, null); if (ref != null) editor = ref.getEditor(activate); } finally { partBeingOpened = false; } if (editor != null) { setEditorAreaVisible(true); if (activate) { if (editor instanceof AbstractMultiEditor) activate(((AbstractMultiEditor) editor).getActiveEditor()); else activate(editor); } else bringToTop(editor); } return ref; } public void resetHiddenEditors() { IEditorReference[] refs = (IEditorReference[]) removedEditors .toArray(new IEditorReference[removedEditors.size()]); for (int i = 0; i < refs.length; i++) { showEditor(refs[i]); } } }